3 * linux/drivers/s390/net/qeth_fs.c
5 * Linux on zSeries OSA Express and HiperSockets support
6 * This file contains code related to procfs.
8 * Copyright 2000,2003 IBM Corporation
10 * Author(s): Thomas Spatzier <tspat@de.ibm.com>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/proc_fs.h>
16 #include <linux/seq_file.h>
17 #include <linux/list.h>
18 #include <linux/rwsem.h>
24 /***** /proc/qeth *****/
25 #define QETH_PROCFILE_NAME "qeth"
26 static struct proc_dir_entry
*qeth_procfile
;
29 qeth_procfile_seq_match(struct device
*dev
, void *data
)
35 qeth_procfile_seq_start(struct seq_file
*s
, loff_t
*offset
)
37 struct device
*dev
= NULL
;
40 down_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
42 return SEQ_START_TOKEN
;
44 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
45 NULL
, qeth_procfile_seq_match
);
54 qeth_procfile_seq_stop(struct seq_file
*s
, void* it
)
56 up_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
60 qeth_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
62 struct device
*prev
, *next
;
64 if (it
== SEQ_START_TOKEN
)
67 prev
= (struct device
*) it
;
68 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
,
69 prev
, NULL
, qeth_procfile_seq_match
);
74 static inline const char *
75 qeth_get_router_str(struct qeth_card
*card
, int ipv
)
77 enum qeth_routing_types routing_type
= NO_ROUTER
;
80 routing_type
= card
->options
.route4
.type
;
82 #ifdef CONFIG_QETH_IPV6
83 routing_type
= card
->options
.route6
.type
;
86 #endif /* CONFIG_QETH_IPV6 */
89 switch (routing_type
){
92 case SECONDARY_ROUTER
:
94 case MULTICAST_ROUTER
:
95 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
98 case PRIMARY_CONNECTOR
:
99 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
102 case SECONDARY_CONNECTOR
:
103 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
106 default: /* NO_ROUTER */
112 qeth_procfile_seq_show(struct seq_file
*s
, void *it
)
114 struct device
*device
;
115 struct qeth_card
*card
;
116 char tmp
[12]; /* for qeth_get_prioq_str */
118 if (it
== SEQ_START_TOKEN
){
119 seq_printf(s
, "devices CHPID interface "
120 "cardtype port chksum prio-q'ing rtr4 "
122 seq_printf(s
, "-------------------------- ----- ---------- "
123 "-------------- ---- ------ ---------- ---- "
124 "---- ----- -----\n");
126 device
= (struct device
*) it
;
127 card
= device
->driver_data
;
128 seq_printf(s
, "%s/%s/%s x%02X %-10s %-14s %-4i ",
133 QETH_CARD_IFNAME(card
),
134 qeth_get_cardname_short(card
),
136 if (card
->lan_online
)
137 seq_printf(s
, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
138 qeth_get_checksum_str(card
),
139 qeth_get_prioq_str(card
, tmp
),
140 qeth_get_router_str(card
, 4),
141 qeth_get_router_str(card
, 6),
142 qeth_get_bufsize_str(card
),
143 card
->qdio
.in_buf_pool
.buf_count
);
145 seq_printf(s
, " +++ LAN OFFLINE +++\n");
151 static struct seq_operations qeth_procfile_seq_ops
= {
152 .start
= qeth_procfile_seq_start
,
153 .stop
= qeth_procfile_seq_stop
,
154 .next
= qeth_procfile_seq_next
,
155 .show
= qeth_procfile_seq_show
,
159 qeth_procfile_open(struct inode
*inode
, struct file
*file
)
161 return seq_open(file
, &qeth_procfile_seq_ops
);
164 static struct file_operations qeth_procfile_fops
= {
165 .owner
= THIS_MODULE
,
166 .open
= qeth_procfile_open
,
169 .release
= seq_release
,
172 /***** /proc/qeth_perf *****/
173 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
174 static struct proc_dir_entry
*qeth_perf_procfile
;
177 qeth_perf_procfile_seq_show(struct seq_file
*s
, void *it
)
179 struct device
*device
;
180 struct qeth_card
*card
;
183 if (it
== SEQ_START_TOKEN
)
186 device
= (struct device
*) it
;
187 card
= device
->driver_data
;
188 seq_printf(s
, "For card with devnos %s/%s/%s (%s):\n",
192 QETH_CARD_IFNAME(card
)
194 if (!card
->options
.performance_stats
)
195 seq_printf(s
, "Performance statistics are deactivated.\n");
196 seq_printf(s
, " Skb's/buffers received : %lu/%u\n"
197 " Skb's/buffers sent : %lu/%u\n\n",
198 card
->stats
.rx_packets
-
199 card
->perf_stats
.initial_rx_packets
,
200 card
->perf_stats
.bufs_rec
,
201 card
->stats
.tx_packets
-
202 card
->perf_stats
.initial_tx_packets
,
203 card
->perf_stats
.bufs_sent
205 seq_printf(s
, " Skb's/buffers sent without packing : %lu/%u\n"
206 " Skb's/buffers sent with packing : %u/%u\n\n",
207 card
->stats
.tx_packets
- card
->perf_stats
.initial_tx_packets
208 - card
->perf_stats
.skbs_sent_pack
,
209 card
->perf_stats
.bufs_sent
- card
->perf_stats
.bufs_sent_pack
,
210 card
->perf_stats
.skbs_sent_pack
,
211 card
->perf_stats
.bufs_sent_pack
213 seq_printf(s
, " Skbs sent in SG mode : %u\n"
214 " Skb fragments sent in SG mode : %u\n\n",
215 card
->perf_stats
.sg_skbs_sent
,
216 card
->perf_stats
.sg_frags_sent
);
217 seq_printf(s
, " large_send tx (in Kbytes) : %u\n"
218 " large_send count : %u\n\n",
219 card
->perf_stats
.large_send_bytes
>> 10,
220 card
->perf_stats
.large_send_cnt
);
221 seq_printf(s
, " Packing state changes no pkg.->packing : %u/%u\n"
222 " Watermarks L/H : %i/%i\n"
223 " Current buffer usage (outbound q's) : "
225 card
->perf_stats
.sc_dp_p
, card
->perf_stats
.sc_p_dp
,
226 QETH_LOW_WATERMARK_PACK
, QETH_HIGH_WATERMARK_PACK
,
227 atomic_read(&card
->qdio
.out_qs
[0]->used_buffers
),
228 (card
->qdio
.no_out_queues
> 1)?
229 atomic_read(&card
->qdio
.out_qs
[1]->used_buffers
)
231 (card
->qdio
.no_out_queues
> 2)?
232 atomic_read(&card
->qdio
.out_qs
[2]->used_buffers
)
234 (card
->qdio
.no_out_queues
> 3)?
235 atomic_read(&card
->qdio
.out_qs
[3]->used_buffers
)
238 seq_printf(s
, " Inbound handler time (in us) : %u\n"
239 " Inbound handler count : %u\n"
240 " Inbound do_QDIO time (in us) : %u\n"
241 " Inbound do_QDIO count : %u\n\n"
242 " Outbound handler time (in us) : %u\n"
243 " Outbound handler count : %u\n\n"
244 " Outbound time (in us, incl QDIO) : %u\n"
245 " Outbound count : %u\n"
246 " Outbound do_QDIO time (in us) : %u\n"
247 " Outbound do_QDIO count : %u\n\n",
248 card
->perf_stats
.inbound_time
,
249 card
->perf_stats
.inbound_cnt
,
250 card
->perf_stats
.inbound_do_qdio_time
,
251 card
->perf_stats
.inbound_do_qdio_cnt
,
252 card
->perf_stats
.outbound_handler_time
,
253 card
->perf_stats
.outbound_handler_cnt
,
254 card
->perf_stats
.outbound_time
,
255 card
->perf_stats
.outbound_cnt
,
256 card
->perf_stats
.outbound_do_qdio_time
,
257 card
->perf_stats
.outbound_do_qdio_cnt
263 static struct seq_operations qeth_perf_procfile_seq_ops
= {
264 .start
= qeth_procfile_seq_start
,
265 .stop
= qeth_procfile_seq_stop
,
266 .next
= qeth_procfile_seq_next
,
267 .show
= qeth_perf_procfile_seq_show
,
271 qeth_perf_procfile_open(struct inode
*inode
, struct file
*file
)
273 return seq_open(file
, &qeth_perf_procfile_seq_ops
);
276 static struct file_operations qeth_perf_procfile_fops
= {
277 .owner
= THIS_MODULE
,
278 .open
= qeth_perf_procfile_open
,
281 .release
= seq_release
,
285 qeth_create_procfs_entries(void)
287 qeth_procfile
= create_proc_entry(QETH_PROCFILE_NAME
,
288 S_IFREG
| 0444, NULL
);
290 qeth_procfile
->proc_fops
= &qeth_procfile_fops
;
292 qeth_perf_procfile
= create_proc_entry(QETH_PERF_PROCFILE_NAME
,
293 S_IFREG
| 0444, NULL
);
294 if (qeth_perf_procfile
)
295 qeth_perf_procfile
->proc_fops
= &qeth_perf_procfile_fops
;
305 qeth_remove_procfs_entries(void)
308 remove_proc_entry(QETH_PROCFILE_NAME
, NULL
);
309 if (qeth_perf_procfile
)
310 remove_proc_entry(QETH_PERF_PROCFILE_NAME
, NULL
);