3 * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.10 $)
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.10 $";
26 /***** /proc/qeth *****/
27 #define QETH_PROCFILE_NAME "qeth"
28 static struct proc_dir_entry *qeth_procfile;
31 qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
33 struct list_head *next_card = NULL;
36 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
39 return SEQ_START_TOKEN;
41 /* get card at pos *offset */
42 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
50 qeth_procfile_seq_stop(struct seq_file *s, void* it)
52 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
56 qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
58 struct list_head *next_card = NULL;
59 struct list_head *current_card;
61 if (it == SEQ_START_TOKEN) {
62 next_card = qeth_ccwgroup_driver.driver.devices.next;
63 if (next_card->next == next_card) /* list empty */
67 current_card = (struct list_head *)it;
68 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
69 return NULL; /* end of list reached */
70 next_card = current_card->next;
77 static inline const char *
78 qeth_get_router_str(struct qeth_card *card, int ipv)
83 routing_type = card->options.route4.type;
85 #ifdef CONFIG_QETH_IPV6
86 routing_type = card->options.route6.type;
89 #endif /* CONFIG_QETH_IPV6 */
92 if (routing_type == PRIMARY_ROUTER)
94 else if (routing_type == SECONDARY_ROUTER)
96 else if (routing_type == MULTICAST_ROUTER) {
97 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
100 } else if (routing_type == PRIMARY_CONNECTOR) {
101 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
104 } else if (routing_type == SECONDARY_CONNECTOR) {
105 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
108 } else if (routing_type == NO_ROUTER)
115 qeth_procfile_seq_show(struct seq_file *s, void *it)
117 struct device *device;
118 struct qeth_card *card;
119 char tmp[12]; /* for qeth_get_prioq_str */
121 if (it == SEQ_START_TOKEN){
122 seq_printf(s, "devices CHPID interface "
123 "cardtype port chksum prio-q'ing rtr4 "
125 seq_printf(s, "-------------------------- ----- ---------- "
126 "-------------- ---- ------ ---------- ---- "
127 "---- ----- -----\n");
129 device = list_entry(it, struct device, driver_list);
130 card = device->driver_data;
131 seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
137 qeth_get_cardname_short(card),
139 if (card->lan_online)
140 seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
141 qeth_get_checksum_str(card),
142 qeth_get_prioq_str(card, tmp),
143 qeth_get_router_str(card, 4),
144 qeth_get_router_str(card, 6),
145 qeth_get_bufsize_str(card),
146 card->qdio.in_buf_pool.buf_count);
148 seq_printf(s, " +++ LAN OFFLINE +++\n");
153 static struct seq_operations qeth_procfile_seq_ops = {
154 .start = qeth_procfile_seq_start,
155 .stop = qeth_procfile_seq_stop,
156 .next = qeth_procfile_seq_next,
157 .show = qeth_procfile_seq_show,
161 qeth_procfile_open(struct inode *inode, struct file *file)
163 return seq_open(file, &qeth_procfile_seq_ops);
166 static struct file_operations qeth_procfile_fops = {
167 .owner = THIS_MODULE,
168 .open = qeth_procfile_open,
171 .release = seq_release,
174 /***** /proc/qeth_perf *****/
175 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
176 static struct proc_dir_entry *qeth_perf_procfile;
178 #ifdef CONFIG_QETH_PERF_STATS
181 qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
183 struct list_head *next_card = NULL;
186 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
187 /* get card at pos *offset */
188 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
197 qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
199 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
203 qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
205 struct list_head *current_card = (struct list_head *)it;
207 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
208 return NULL; /* end of list reached */
210 return current_card->next;
214 qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
216 struct device *device;
217 struct qeth_card *card;
219 device = list_entry(it, struct device, driver_list);
220 card = device->driver_data;
221 seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
227 seq_printf(s, " Skb's/buffers received : %li/%i\n"
228 " Skb's/buffers sent : %li/%i\n\n",
229 card->stats.rx_packets, card->perf_stats.bufs_rec,
230 card->stats.tx_packets, card->perf_stats.bufs_sent
232 seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n"
233 " Skb's/buffers sent with packing : %i/%i\n\n",
234 card->stats.tx_packets - card->perf_stats.skbs_sent_pack,
235 card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
236 card->perf_stats.skbs_sent_pack,
237 card->perf_stats.bufs_sent_pack
239 seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
240 " Watermarks L/H : %i/%i\n"
241 " Current buffer usage (outbound q's) : "
243 card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
244 QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
245 atomic_read(&card->qdio.out_qs[0]->used_buffers),
246 (card->qdio.no_out_queues > 1)?
247 atomic_read(&card->qdio.out_qs[1]->used_buffers)
249 (card->qdio.no_out_queues > 2)?
250 atomic_read(&card->qdio.out_qs[2]->used_buffers)
252 (card->qdio.no_out_queues > 3)?
253 atomic_read(&card->qdio.out_qs[3]->used_buffers)
256 seq_printf(s, " Inbound handler time (in us) : %i\n"
257 " Inbound handler count : %i\n"
258 " Inbound do_QDIO time (in us) : %i\n"
259 " Inbound do_QDIO count : %i\n\n"
260 " Outbound handler time (in us) : %i\n"
261 " Outbound handler count : %i\n\n"
262 " Outbound time (in us, incl QDIO) : %i\n"
263 " Outbound count : %i\n"
264 " Outbound do_QDIO time (in us) : %i\n"
265 " Outbound do_QDIO count : %i\n",
266 card->perf_stats.inbound_time,
267 card->perf_stats.inbound_cnt,
268 card->perf_stats.inbound_do_qdio_time,
269 card->perf_stats.inbound_do_qdio_cnt,
270 card->perf_stats.outbound_handler_time,
271 card->perf_stats.outbound_handler_cnt,
272 card->perf_stats.outbound_time,
273 card->perf_stats.outbound_cnt,
274 card->perf_stats.outbound_do_qdio_time,
275 card->perf_stats.outbound_do_qdio_cnt
281 static struct seq_operations qeth_perf_procfile_seq_ops = {
282 .start = qeth_perf_procfile_seq_start,
283 .stop = qeth_perf_procfile_seq_stop,
284 .next = qeth_perf_procfile_seq_next,
285 .show = qeth_perf_procfile_seq_show,
289 qeth_perf_procfile_open(struct inode *inode, struct file *file)
291 return seq_open(file, &qeth_perf_procfile_seq_ops);
294 static struct file_operations qeth_perf_procfile_fops = {
295 .owner = THIS_MODULE,
296 .open = qeth_perf_procfile_open,
299 .release = seq_release,
302 #define qeth_perf_procfile_created qeth_perf_procfile
304 #define qeth_perf_procfile_created 1
305 #endif /* CONFIG_QETH_PERF_STATS */
307 /***** /proc/qeth_ipa_takeover *****/
308 #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover"
309 static struct proc_dir_entry *qeth_ipato_procfile;
312 qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
314 struct list_head *next_card = NULL;
317 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
318 /* TODO: finish this */
320 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
321 * output driver settings then;
322 * else output setting for respective card
324 /* get card at pos *offset */
325 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
334 qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
336 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
340 qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
342 struct list_head *current_card = (struct list_head *)it;
344 /* TODO: finish this */
346 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
347 * output driver settings then;
348 * else output setting for respective card
350 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
351 return NULL; /* end of list reached */
353 return current_card->next;
357 qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
359 struct device *device;
360 struct qeth_card *card;
362 /* TODO: finish this */
364 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
365 * output driver settings then;
366 * else output setting for respective card
368 device = list_entry(it, struct device, driver_list);
369 card = device->driver_data;
374 static struct seq_operations qeth_ipato_procfile_seq_ops = {
375 .start = qeth_ipato_procfile_seq_start,
376 .stop = qeth_ipato_procfile_seq_stop,
377 .next = qeth_ipato_procfile_seq_next,
378 .show = qeth_ipato_procfile_seq_show,
382 qeth_ipato_procfile_open(struct inode *inode, struct file *file)
384 return seq_open(file, &qeth_ipato_procfile_seq_ops);
387 static struct file_operations qeth_ipato_procfile_fops = {
388 .owner = THIS_MODULE,
389 .open = qeth_ipato_procfile_open,
392 .release = seq_release,
396 qeth_create_procfs_entries(void)
398 qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
399 S_IFREG | 0444, NULL);
401 qeth_procfile->proc_fops = &qeth_procfile_fops;
403 #ifdef CONFIG_QETH_PERF_STATS
404 qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
405 S_IFREG | 0444, NULL);
406 if (qeth_perf_procfile)
407 qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
408 #endif /* CONFIG_QETH_PERF_STATS */
410 qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME,
411 S_IFREG | 0444, NULL);
412 if (qeth_ipato_procfile)
413 qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops;
416 qeth_ipato_procfile &&
417 qeth_perf_procfile_created)
424 qeth_remove_procfs_entries(void)
427 remove_proc_entry(QETH_PROCFILE_NAME, NULL);
428 if (qeth_perf_procfile)
429 remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
430 if (qeth_ipato_procfile)
431 remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL);
435 /* ONLY FOR DEVELOPMENT! -> make it as module */
438 qeth_create_sysfs_entries(void)
442 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
444 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
446 qeth_create_device_attributes(dev);
448 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
452 qeth_remove_sysfs_entries(void)
456 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
458 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
460 qeth_remove_device_attributes(dev);
462 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
468 printk(KERN_INFO "qeth_fs_init\n");
469 qeth_create_procfs_entries();
470 qeth_create_sysfs_entries();
478 printk(KERN_INFO "qeth_fs_exit\n");
479 qeth_remove_procfs_entries();
480 qeth_remove_sysfs_entries();
484 module_init(qeth_fs_init);
485 module_exit(qeth_fs_exit);
487 MODULE_LICENSE("GPL");