3 * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.5 $)
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_start(struct seq_file *s, loff_t *offset)
31 struct list_head *next_card = NULL;
34 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
37 return SEQ_START_TOKEN;
39 /* get card at pos *offset */
40 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
48 qeth_procfile_seq_stop(struct seq_file *s, void* it)
50 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
54 qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
56 struct list_head *next_card = NULL;
57 struct list_head *current_card;
59 if (it == SEQ_START_TOKEN) {
60 next_card = qeth_ccwgroup_driver.driver.devices.next;
61 if (next_card->next == next_card) /* list empty */
65 current_card = (struct list_head *)it;
66 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
67 return NULL; /* end of list reached */
68 next_card = current_card->next;
75 static inline const char *
76 qeth_get_router_str(struct qeth_card *card, int ipv)
81 routing_type = card->options.route4.type;
83 #ifdef CONFIG_QETH_IPV6
84 routing_type = card->options.route6.type;
87 #endif /* CONFIG_QETH_IPV6 */
90 if (routing_type == PRIMARY_ROUTER)
92 else if (routing_type == SECONDARY_ROUTER)
94 else if (routing_type == MULTICAST_ROUTER)
96 else if (routing_type == PRIMARY_CONNECTOR)
98 else if (routing_type == SECONDARY_CONNECTOR)
100 else if (routing_type == NO_ROUTER)
107 qeth_procfile_seq_show(struct seq_file *s, void *it)
109 struct device *device;
110 struct qeth_card *card;
111 char tmp[12]; /* for qeth_get_prioq_str */
113 if (it == SEQ_START_TOKEN){
114 seq_printf(s, "devices CHPID interface "
115 "cardtype port chksum prio-q'ing rtr4 "
117 seq_printf(s, "-------------------------- ----- ---------- "
118 "-------------- ---- ------ ---------- ---- "
119 "---- ----- -----\n");
121 device = list_entry(it, struct device, driver_list);
122 card = device->driver_data;
123 seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
129 qeth_get_cardname_short(card),
131 if (card->lan_online)
132 seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
133 qeth_get_checksum_str(card),
134 qeth_get_prioq_str(card, tmp),
135 qeth_get_router_str(card, 4),
136 qeth_get_router_str(card, 6),
137 qeth_get_bufsize_str(card),
138 card->qdio.in_buf_pool.buf_count);
140 seq_printf(s, " +++ LAN OFFLINE +++\n");
145 static struct seq_operations qeth_procfile_seq_ops = {
146 .start = qeth_procfile_seq_start,
147 .stop = qeth_procfile_seq_stop,
148 .next = qeth_procfile_seq_next,
149 .show = qeth_procfile_seq_show,
153 qeth_procfile_open(struct inode *inode, struct file *file)
155 return seq_open(file, &qeth_procfile_seq_ops);
158 static struct file_operations qeth_procfile_fops = {
159 .owner = THIS_MODULE,
160 .open = qeth_procfile_open,
163 .release = seq_release,
166 /***** /proc/qeth_perf *****/
167 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
168 static struct proc_dir_entry *qeth_perf_procfile;
170 #ifdef CONFIG_QETH_PERF_STATS
173 qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
175 struct list_head *next_card = NULL;
178 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
179 /* get card at pos *offset */
180 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
189 qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
191 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
195 qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
197 struct list_head *current_card = (struct list_head *)it;
199 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
200 return NULL; /* end of list reached */
202 return current_card->next;
206 qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
208 struct device *device;
209 struct qeth_card *card;
211 device = list_entry(it, struct device, driver_list);
212 card = device->driver_data;
213 seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
219 seq_printf(s, " Skb's/buffers received : %li/%i\n"
220 " Skb's/buffers sent : %li/%i\n\n",
221 card->stats.rx_packets, card->perf_stats.bufs_rec,
222 card->stats.tx_packets, card->perf_stats.bufs_sent
224 seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n"
225 " Skb's/buffers sent with packing : %i/%i\n\n",
226 card->stats.tx_packets - card->perf_stats.skbs_sent_pack,
227 card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
228 card->perf_stats.skbs_sent_pack,
229 card->perf_stats.bufs_sent_pack
231 seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
232 " Current buffer usage (outbound q's) : "
234 card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
235 atomic_read(&card->qdio.out_qs[0]->used_buffers),
236 (card->qdio.no_out_queues > 1)?
237 atomic_read(&card->qdio.out_qs[1]->used_buffers)
239 (card->qdio.no_out_queues > 2)?
240 atomic_read(&card->qdio.out_qs[2]->used_buffers)
242 (card->qdio.no_out_queues > 3)?
243 atomic_read(&card->qdio.out_qs[3]->used_buffers)
246 seq_printf(s, " Inbound time (in us) : %i\n"
247 " Inbound cnt : %i\n"
248 " Outbound time (in us, incl QDIO) : %i\n"
249 " Outbound cnt : %i\n"
250 " Watermarks L/H : %i/%i\n\n",
251 card->perf_stats.inbound_time,
252 card->perf_stats.inbound_cnt,
253 card->perf_stats.outbound_time,
254 card->perf_stats.outbound_cnt,
255 QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK
261 static struct seq_operations qeth_perf_procfile_seq_ops = {
262 .start = qeth_perf_procfile_seq_start,
263 .stop = qeth_perf_procfile_seq_stop,
264 .next = qeth_perf_procfile_seq_next,
265 .show = qeth_perf_procfile_seq_show,
269 qeth_perf_procfile_open(struct inode *inode, struct file *file)
271 return seq_open(file, &qeth_perf_procfile_seq_ops);
274 static struct file_operations qeth_perf_procfile_fops = {
275 .owner = THIS_MODULE,
276 .open = qeth_perf_procfile_open,
279 .release = seq_release,
282 #define qeth_perf_procfile_created qeth_perf_procfile
284 #define qeth_perf_procfile_created 1
285 #endif /* CONFIG_QETH_PERF_STATS */
287 /***** /proc/qeth_ipa_takeover *****/
288 #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover"
289 static struct proc_dir_entry *qeth_ipato_procfile;
292 qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
294 struct list_head *next_card = NULL;
297 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
298 /* TODO: finish this */
300 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
301 * output driver settings then;
302 * else output setting for respective card
304 /* get card at pos *offset */
305 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
314 qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
316 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
320 qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
322 struct list_head *current_card = (struct list_head *)it;
324 /* TODO: finish this */
326 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
327 * output driver settings then;
328 * else output setting for respective card
330 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
331 return NULL; /* end of list reached */
333 return current_card->next;
337 qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
339 struct device *device;
340 struct qeth_card *card;
342 /* TODO: finish this */
344 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
345 * output driver settings then;
346 * else output setting for respective card
348 device = list_entry(it, struct device, driver_list);
349 card = device->driver_data;
354 static struct seq_operations qeth_ipato_procfile_seq_ops = {
355 .start = qeth_ipato_procfile_seq_start,
356 .stop = qeth_ipato_procfile_seq_stop,
357 .next = qeth_ipato_procfile_seq_next,
358 .show = qeth_ipato_procfile_seq_show,
362 qeth_ipato_procfile_open(struct inode *inode, struct file *file)
364 return seq_open(file, &qeth_ipato_procfile_seq_ops);
367 static struct file_operations qeth_ipato_procfile_fops = {
368 .owner = THIS_MODULE,
369 .open = qeth_ipato_procfile_open,
372 .release = seq_release,
376 qeth_create_procfs_entries(void)
378 qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
379 S_IFREG | 0444, NULL);
381 qeth_procfile->proc_fops = &qeth_procfile_fops;
383 #ifdef CONFIG_QETH_PERF_STATS
384 qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
385 S_IFREG | 0444, NULL);
386 if (qeth_perf_procfile)
387 qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
388 #endif /* CONFIG_QETH_PERF_STATS */
390 qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME,
391 S_IFREG | 0444, NULL);
392 if (qeth_ipato_procfile)
393 qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops;
396 qeth_ipato_procfile &&
397 qeth_perf_procfile_created)
404 qeth_remove_procfs_entries(void)
407 remove_proc_entry(QETH_PROCFILE_NAME, NULL);
408 if (qeth_perf_procfile)
409 remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
410 if (qeth_ipato_procfile)
411 remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL);
415 /* ONLY FOR DEVELOPMENT! -> make it as module */
418 qeth_create_sysfs_entries(void)
422 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
424 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
426 qeth_create_device_attributes(dev);
428 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
432 qeth_remove_sysfs_entries(void)
436 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
438 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
440 qeth_remove_device_attributes(dev);
442 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
448 printk(KERN_INFO "qeth_fs_init\n");
449 qeth_create_procfs_entries();
450 qeth_create_sysfs_entries();
458 printk(KERN_INFO "qeth_fs_exit\n");
459 qeth_remove_procfs_entries();
460 qeth_remove_sysfs_entries();
464 module_init(qeth_fs_init);
465 module_exit(qeth_fs_exit);
467 MODULE_LICENSE("GPL");