3 * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.13 $)
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 const char *VERSION_QETH_PROC_C
= "$Revision: 1.13 $";
26 /***** /proc/qeth *****/
27 #define QETH_PROCFILE_NAME "qeth"
28 static struct proc_dir_entry
*qeth_procfile
;
31 qeth_procfile_seq_match(struct device
*dev
, void *data
)
37 qeth_procfile_seq_start(struct seq_file
*s
, loff_t
*offset
)
42 down_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
46 return SEQ_START_TOKEN
;
48 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, NULL
,
49 NULL
, qeth_procfile_seq_match
);
51 /* get card at pos *offset */
53 while (nr
-- > 1 && dev
)
54 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
55 NULL
, qeth_procfile_seq_match
);
60 qeth_procfile_seq_stop(struct seq_file
*s
, void* it
)
62 up_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
66 qeth_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
68 struct device
*prev
, *next
;
70 if (it
== SEQ_START_TOKEN
) {
71 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
,
72 NULL
, NULL
, qeth_procfile_seq_match
);
77 prev
= (struct device
*) it
;
78 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
,
79 prev
, NULL
, qeth_procfile_seq_match
);
85 static inline const char *
86 qeth_get_router_str(struct qeth_card
*card
, int ipv
)
91 routing_type
= card
->options
.route4
.type
;
93 #ifdef CONFIG_QETH_IPV6
94 routing_type
= card
->options
.route6
.type
;
97 #endif /* CONFIG_QETH_IPV6 */
100 if (routing_type
== PRIMARY_ROUTER
)
102 else if (routing_type
== SECONDARY_ROUTER
)
104 else if (routing_type
== MULTICAST_ROUTER
) {
105 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
108 } else if (routing_type
== PRIMARY_CONNECTOR
) {
109 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
112 } else if (routing_type
== SECONDARY_CONNECTOR
) {
113 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
116 } else if (routing_type
== NO_ROUTER
)
123 qeth_procfile_seq_show(struct seq_file
*s
, void *it
)
125 struct device
*device
;
126 struct qeth_card
*card
;
127 char tmp
[12]; /* for qeth_get_prioq_str */
129 if (it
== SEQ_START_TOKEN
){
130 seq_printf(s
, "devices CHPID interface "
131 "cardtype port chksum prio-q'ing rtr4 "
133 seq_printf(s
, "-------------------------- ----- ---------- "
134 "-------------- ---- ------ ---------- ---- "
135 "---- ----- -----\n");
137 device
= (struct device
*) it
;
138 card
= device
->driver_data
;
139 seq_printf(s
, "%s/%s/%s x%02X %-10s %-14s %-4i ",
144 QETH_CARD_IFNAME(card
),
145 qeth_get_cardname_short(card
),
147 if (card
->lan_online
)
148 seq_printf(s
, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
149 qeth_get_checksum_str(card
),
150 qeth_get_prioq_str(card
, tmp
),
151 qeth_get_router_str(card
, 4),
152 qeth_get_router_str(card
, 6),
153 qeth_get_bufsize_str(card
),
154 card
->qdio
.in_buf_pool
.buf_count
);
156 seq_printf(s
, " +++ LAN OFFLINE +++\n");
161 static struct seq_operations qeth_procfile_seq_ops
= {
162 .start
= qeth_procfile_seq_start
,
163 .stop
= qeth_procfile_seq_stop
,
164 .next
= qeth_procfile_seq_next
,
165 .show
= qeth_procfile_seq_show
,
169 qeth_procfile_open(struct inode
*inode
, struct file
*file
)
171 return seq_open(file
, &qeth_procfile_seq_ops
);
174 static struct file_operations qeth_procfile_fops
= {
175 .owner
= THIS_MODULE
,
176 .open
= qeth_procfile_open
,
179 .release
= seq_release
,
182 /***** /proc/qeth_perf *****/
183 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
184 static struct proc_dir_entry
*qeth_perf_procfile
;
186 #ifdef CONFIG_QETH_PERF_STATS
189 qeth_perf_procfile_seq_start(struct seq_file
*s
, loff_t
*offset
)
191 struct device
*dev
= NULL
;
194 down_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
195 /* get card at pos *offset */
196 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, NULL
, NULL
,
197 qeth_procfile_seq_match
);
199 /* get card at pos *offset */
201 while (nr
-- > 1 && dev
)
202 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
203 NULL
, qeth_procfile_seq_match
);
208 qeth_perf_procfile_seq_stop(struct seq_file
*s
, void* it
)
210 up_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
214 qeth_perf_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
216 struct device
*prev
, *next
;
218 prev
= (struct device
*) it
;
219 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
, prev
,
220 NULL
, qeth_procfile_seq_match
);
223 return (void *) next
;
227 qeth_perf_procfile_seq_show(struct seq_file
*s
, void *it
)
229 struct device
*device
;
230 struct qeth_card
*card
;
232 device
= (struct device
*) it
;
233 card
= device
->driver_data
;
234 seq_printf(s
, "For card with devnos %s/%s/%s (%s):\n",
238 QETH_CARD_IFNAME(card
)
240 seq_printf(s
, " Skb's/buffers received : %li/%i\n"
241 " Skb's/buffers sent : %li/%i\n\n",
242 card
->stats
.rx_packets
, card
->perf_stats
.bufs_rec
,
243 card
->stats
.tx_packets
, card
->perf_stats
.bufs_sent
245 seq_printf(s
, " Skb's/buffers sent without packing : %li/%i\n"
246 " Skb's/buffers sent with packing : %i/%i\n\n",
247 card
->stats
.tx_packets
- card
->perf_stats
.skbs_sent_pack
,
248 card
->perf_stats
.bufs_sent
- card
->perf_stats
.bufs_sent_pack
,
249 card
->perf_stats
.skbs_sent_pack
,
250 card
->perf_stats
.bufs_sent_pack
252 seq_printf(s
, " Skbs sent in SG mode : %i\n"
253 " Skb fragments sent in SG mode : %i\n\n",
254 card
->perf_stats
.sg_skbs_sent
,
255 card
->perf_stats
.sg_frags_sent
);
256 seq_printf(s
, " large_send tx (in Kbytes) : %i\n"
257 " large_send count : %i\n\n",
258 card
->perf_stats
.large_send_bytes
>> 10,
259 card
->perf_stats
.large_send_cnt
);
260 seq_printf(s
, " Packing state changes no pkg.->packing : %i/%i\n"
261 " Watermarks L/H : %i/%i\n"
262 " Current buffer usage (outbound q's) : "
264 card
->perf_stats
.sc_dp_p
, card
->perf_stats
.sc_p_dp
,
265 QETH_LOW_WATERMARK_PACK
, QETH_HIGH_WATERMARK_PACK
,
266 atomic_read(&card
->qdio
.out_qs
[0]->used_buffers
),
267 (card
->qdio
.no_out_queues
> 1)?
268 atomic_read(&card
->qdio
.out_qs
[1]->used_buffers
)
270 (card
->qdio
.no_out_queues
> 2)?
271 atomic_read(&card
->qdio
.out_qs
[2]->used_buffers
)
273 (card
->qdio
.no_out_queues
> 3)?
274 atomic_read(&card
->qdio
.out_qs
[3]->used_buffers
)
277 seq_printf(s
, " Inbound handler time (in us) : %i\n"
278 " Inbound handler count : %i\n"
279 " Inbound do_QDIO time (in us) : %i\n"
280 " Inbound do_QDIO count : %i\n\n"
281 " Outbound handler time (in us) : %i\n"
282 " Outbound handler count : %i\n\n"
283 " Outbound time (in us, incl QDIO) : %i\n"
284 " Outbound count : %i\n"
285 " Outbound do_QDIO time (in us) : %i\n"
286 " Outbound do_QDIO count : %i\n\n",
287 card
->perf_stats
.inbound_time
,
288 card
->perf_stats
.inbound_cnt
,
289 card
->perf_stats
.inbound_do_qdio_time
,
290 card
->perf_stats
.inbound_do_qdio_cnt
,
291 card
->perf_stats
.outbound_handler_time
,
292 card
->perf_stats
.outbound_handler_cnt
,
293 card
->perf_stats
.outbound_time
,
294 card
->perf_stats
.outbound_cnt
,
295 card
->perf_stats
.outbound_do_qdio_time
,
296 card
->perf_stats
.outbound_do_qdio_cnt
301 static struct seq_operations qeth_perf_procfile_seq_ops
= {
302 .start
= qeth_perf_procfile_seq_start
,
303 .stop
= qeth_perf_procfile_seq_stop
,
304 .next
= qeth_perf_procfile_seq_next
,
305 .show
= qeth_perf_procfile_seq_show
,
309 qeth_perf_procfile_open(struct inode
*inode
, struct file
*file
)
311 return seq_open(file
, &qeth_perf_procfile_seq_ops
);
314 static struct file_operations qeth_perf_procfile_fops
= {
315 .owner
= THIS_MODULE
,
316 .open
= qeth_perf_procfile_open
,
319 .release
= seq_release
,
322 #define qeth_perf_procfile_created qeth_perf_procfile
324 #define qeth_perf_procfile_created 1
325 #endif /* CONFIG_QETH_PERF_STATS */
327 /***** /proc/qeth_ipa_takeover *****/
328 #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover"
329 static struct proc_dir_entry
*qeth_ipato_procfile
;
332 qeth_ipato_procfile_seq_start(struct seq_file
*s
, loff_t
*offset
)
337 down_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
338 /* TODO: finish this */
340 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
341 * output driver settings then;
342 * else output setting for respective card
345 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, NULL
, NULL
,
346 qeth_procfile_seq_match
);
348 /* get card at pos *offset */
350 while (nr
-- > 1 && dev
)
351 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
352 NULL
, qeth_procfile_seq_match
);
357 qeth_ipato_procfile_seq_stop(struct seq_file
*s
, void* it
)
359 up_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
363 qeth_ipato_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
365 struct device
*prev
, *next
;
367 prev
= (struct device
*) it
;
368 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
, prev
,
369 NULL
, qeth_procfile_seq_match
);
372 return (void *) next
;
376 qeth_ipato_procfile_seq_show(struct seq_file
*s
, void *it
)
378 struct device
*device
;
379 struct qeth_card
*card
;
381 /* TODO: finish this */
383 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
384 * output driver settings then;
385 * else output setting for respective card
387 device
= (struct device
*) it
;
388 card
= device
->driver_data
;
393 static struct seq_operations qeth_ipato_procfile_seq_ops
= {
394 .start
= qeth_ipato_procfile_seq_start
,
395 .stop
= qeth_ipato_procfile_seq_stop
,
396 .next
= qeth_ipato_procfile_seq_next
,
397 .show
= qeth_ipato_procfile_seq_show
,
401 qeth_ipato_procfile_open(struct inode
*inode
, struct file
*file
)
403 return seq_open(file
, &qeth_ipato_procfile_seq_ops
);
406 static struct file_operations qeth_ipato_procfile_fops
= {
407 .owner
= THIS_MODULE
,
408 .open
= qeth_ipato_procfile_open
,
411 .release
= seq_release
,
415 qeth_create_procfs_entries(void)
417 qeth_procfile
= create_proc_entry(QETH_PROCFILE_NAME
,
418 S_IFREG
| 0444, NULL
);
420 qeth_procfile
->proc_fops
= &qeth_procfile_fops
;
422 #ifdef CONFIG_QETH_PERF_STATS
423 qeth_perf_procfile
= create_proc_entry(QETH_PERF_PROCFILE_NAME
,
424 S_IFREG
| 0444, NULL
);
425 if (qeth_perf_procfile
)
426 qeth_perf_procfile
->proc_fops
= &qeth_perf_procfile_fops
;
427 #endif /* CONFIG_QETH_PERF_STATS */
429 qeth_ipato_procfile
= create_proc_entry(QETH_IPATO_PROCFILE_NAME
,
430 S_IFREG
| 0444, NULL
);
431 if (qeth_ipato_procfile
)
432 qeth_ipato_procfile
->proc_fops
= &qeth_ipato_procfile_fops
;
435 qeth_ipato_procfile
&&
436 qeth_perf_procfile_created
)
443 qeth_remove_procfs_entries(void)
446 remove_proc_entry(QETH_PROCFILE_NAME
, NULL
);
447 if (qeth_perf_procfile
)
448 remove_proc_entry(QETH_PERF_PROCFILE_NAME
, NULL
);
449 if (qeth_ipato_procfile
)
450 remove_proc_entry(QETH_IPATO_PROCFILE_NAME
, NULL
);
454 /* ONLY FOR DEVELOPMENT! -> make it as module */
457 qeth_create_sysfs_entries(void)
461 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
463 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
465 qeth_create_device_attributes(dev);
467 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
471 qeth_remove_sysfs_entries(void)
475 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
477 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
479 qeth_remove_device_attributes(dev);
481 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
487 printk(KERN_INFO "qeth_fs_init\n");
488 qeth_create_procfs_entries();
489 qeth_create_sysfs_entries();
497 printk(KERN_INFO "qeth_fs_exit\n");
498 qeth_remove_procfs_entries();
499 qeth_remove_sysfs_entries();
503 module_init(qeth_fs_init);
504 module_exit(qeth_fs_exit);
506 MODULE_LICENSE("GPL");