Linux-2.6.12-rc2
[deliverable/linux.git] / drivers / s390 / net / qeth_proc.c
1 /*
2 *
3 * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.13 $)
4 *
5 * Linux on zSeries OSA Express and HiperSockets support
6 * This file contains code related to procfs.
7 *
8 * Copyright 2000,2003 IBM Corporation
9 *
10 * Author(s): Thomas Spatzier <tspat@de.ibm.com>
11 *
12 */
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>
19
20 #include "qeth.h"
21 #include "qeth_mpc.h"
22 #include "qeth_fs.h"
23
24 const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
25
26 /***** /proc/qeth *****/
27 #define QETH_PROCFILE_NAME "qeth"
28 static struct proc_dir_entry *qeth_procfile;
29
30 static void *
31 qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
32 {
33 struct list_head *next_card = NULL;
34 int i = 0;
35
36 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
37
38 if (*offset == 0)
39 return SEQ_START_TOKEN;
40
41 /* get card at pos *offset */
42 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
43 if (++i == *offset)
44 return next_card;
45
46 return NULL;
47 }
48
49 static void
50 qeth_procfile_seq_stop(struct seq_file *s, void* it)
51 {
52 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
53 }
54
55 static void *
56 qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
57 {
58 struct list_head *next_card = NULL;
59 struct list_head *current_card;
60
61 if (it == SEQ_START_TOKEN) {
62 next_card = qeth_ccwgroup_driver.driver.devices.next;
63 if (next_card->next == next_card) /* list empty */
64 return NULL;
65 (*offset)++;
66 } else {
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;
71 (*offset)++;
72 }
73
74 return next_card;
75 }
76
77 static inline const char *
78 qeth_get_router_str(struct qeth_card *card, int ipv)
79 {
80 int routing_type = 0;
81
82 if (ipv == 4){
83 routing_type = card->options.route4.type;
84 } else {
85 #ifdef CONFIG_QETH_IPV6
86 routing_type = card->options.route6.type;
87 #else
88 return "n/a";
89 #endif /* CONFIG_QETH_IPV6 */
90 }
91
92 if (routing_type == PRIMARY_ROUTER)
93 return "pri";
94 else if (routing_type == SECONDARY_ROUTER)
95 return "sec";
96 else if (routing_type == MULTICAST_ROUTER) {
97 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
98 return "mc+";
99 return "mc";
100 } else if (routing_type == PRIMARY_CONNECTOR) {
101 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
102 return "p+c";
103 return "p.c";
104 } else if (routing_type == SECONDARY_CONNECTOR) {
105 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
106 return "s+c";
107 return "s.c";
108 } else if (routing_type == NO_ROUTER)
109 return "no";
110 else
111 return "unk";
112 }
113
114 static int
115 qeth_procfile_seq_show(struct seq_file *s, void *it)
116 {
117 struct device *device;
118 struct qeth_card *card;
119 char tmp[12]; /* for qeth_get_prioq_str */
120
121 if (it == SEQ_START_TOKEN){
122 seq_printf(s, "devices CHPID interface "
123 "cardtype port chksum prio-q'ing rtr4 "
124 "rtr6 fsz cnt\n");
125 seq_printf(s, "-------------------------- ----- ---------- "
126 "-------------- ---- ------ ---------- ---- "
127 "---- ----- -----\n");
128 } else {
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 ",
132 CARD_RDEV_ID(card),
133 CARD_WDEV_ID(card),
134 CARD_DDEV_ID(card),
135 card->info.chpid,
136 QETH_CARD_IFNAME(card),
137 qeth_get_cardname_short(card),
138 card->info.portno);
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);
147 else
148 seq_printf(s, " +++ LAN OFFLINE +++\n");
149 }
150 return 0;
151 }
152
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,
158 };
159
160 static int
161 qeth_procfile_open(struct inode *inode, struct file *file)
162 {
163 return seq_open(file, &qeth_procfile_seq_ops);
164 }
165
166 static struct file_operations qeth_procfile_fops = {
167 .owner = THIS_MODULE,
168 .open = qeth_procfile_open,
169 .read = seq_read,
170 .llseek = seq_lseek,
171 .release = seq_release,
172 };
173
174 /***** /proc/qeth_perf *****/
175 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
176 static struct proc_dir_entry *qeth_perf_procfile;
177
178 #ifdef CONFIG_QETH_PERF_STATS
179
180 static void *
181 qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
182 {
183 struct list_head *next_card = NULL;
184 int i = 0;
185
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){
189 if (i == *offset)
190 return next_card;
191 i++;
192 }
193 return NULL;
194 }
195
196 static void
197 qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
198 {
199 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
200 }
201
202 static void *
203 qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
204 {
205 struct list_head *current_card = (struct list_head *)it;
206
207 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
208 return NULL; /* end of list reached */
209 (*offset)++;
210 return current_card->next;
211 }
212
213 static int
214 qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
215 {
216 struct device *device;
217 struct qeth_card *card;
218
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",
222 CARD_RDEV_ID(card),
223 CARD_WDEV_ID(card),
224 CARD_DDEV_ID(card),
225 QETH_CARD_IFNAME(card)
226 );
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
231 );
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
238 );
239 seq_printf(s, " Skbs sent in SG mode : %i\n"
240 " Skb fragments sent in SG mode : %i\n\n",
241 card->perf_stats.sg_skbs_sent,
242 card->perf_stats.sg_frags_sent);
243 seq_printf(s, " large_send tx (in Kbytes) : %i\n"
244 " large_send count : %i\n\n",
245 card->perf_stats.large_send_bytes >> 10,
246 card->perf_stats.large_send_cnt);
247 seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
248 " Watermarks L/H : %i/%i\n"
249 " Current buffer usage (outbound q's) : "
250 "%i/%i/%i/%i\n\n",
251 card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
252 QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
253 atomic_read(&card->qdio.out_qs[0]->used_buffers),
254 (card->qdio.no_out_queues > 1)?
255 atomic_read(&card->qdio.out_qs[1]->used_buffers)
256 : 0,
257 (card->qdio.no_out_queues > 2)?
258 atomic_read(&card->qdio.out_qs[2]->used_buffers)
259 : 0,
260 (card->qdio.no_out_queues > 3)?
261 atomic_read(&card->qdio.out_qs[3]->used_buffers)
262 : 0
263 );
264 seq_printf(s, " Inbound handler time (in us) : %i\n"
265 " Inbound handler count : %i\n"
266 " Inbound do_QDIO time (in us) : %i\n"
267 " Inbound do_QDIO count : %i\n\n"
268 " Outbound handler time (in us) : %i\n"
269 " Outbound handler count : %i\n\n"
270 " Outbound time (in us, incl QDIO) : %i\n"
271 " Outbound count : %i\n"
272 " Outbound do_QDIO time (in us) : %i\n"
273 " Outbound do_QDIO count : %i\n\n",
274 card->perf_stats.inbound_time,
275 card->perf_stats.inbound_cnt,
276 card->perf_stats.inbound_do_qdio_time,
277 card->perf_stats.inbound_do_qdio_cnt,
278 card->perf_stats.outbound_handler_time,
279 card->perf_stats.outbound_handler_cnt,
280 card->perf_stats.outbound_time,
281 card->perf_stats.outbound_cnt,
282 card->perf_stats.outbound_do_qdio_time,
283 card->perf_stats.outbound_do_qdio_cnt
284 );
285 return 0;
286 }
287
288 static struct seq_operations qeth_perf_procfile_seq_ops = {
289 .start = qeth_perf_procfile_seq_start,
290 .stop = qeth_perf_procfile_seq_stop,
291 .next = qeth_perf_procfile_seq_next,
292 .show = qeth_perf_procfile_seq_show,
293 };
294
295 static int
296 qeth_perf_procfile_open(struct inode *inode, struct file *file)
297 {
298 return seq_open(file, &qeth_perf_procfile_seq_ops);
299 }
300
301 static struct file_operations qeth_perf_procfile_fops = {
302 .owner = THIS_MODULE,
303 .open = qeth_perf_procfile_open,
304 .read = seq_read,
305 .llseek = seq_lseek,
306 .release = seq_release,
307 };
308
309 #define qeth_perf_procfile_created qeth_perf_procfile
310 #else
311 #define qeth_perf_procfile_created 1
312 #endif /* CONFIG_QETH_PERF_STATS */
313
314 /***** /proc/qeth_ipa_takeover *****/
315 #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover"
316 static struct proc_dir_entry *qeth_ipato_procfile;
317
318 static void *
319 qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
320 {
321 struct list_head *next_card = NULL;
322 int i = 0;
323
324 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
325 /* TODO: finish this */
326 /*
327 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
328 * output driver settings then;
329 * else output setting for respective card
330 */
331 /* get card at pos *offset */
332 list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
333 if (i == *offset)
334 return next_card;
335 i++;
336 }
337 return NULL;
338 }
339
340 static void
341 qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
342 {
343 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
344 }
345
346 static void *
347 qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
348 {
349 struct list_head *current_card = (struct list_head *)it;
350
351 /* TODO: finish this */
352 /*
353 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
354 * output driver settings then;
355 * else output setting for respective card
356 */
357 if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
358 return NULL; /* end of list reached */
359 (*offset)++;
360 return current_card->next;
361 }
362
363 static int
364 qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
365 {
366 struct device *device;
367 struct qeth_card *card;
368
369 /* TODO: finish this */
370 /*
371 * maybe SEQ_SATRT_TOKEN can be returned for offset 0
372 * output driver settings then;
373 * else output setting for respective card
374 */
375 device = list_entry(it, struct device, driver_list);
376 card = device->driver_data;
377
378 return 0;
379 }
380
381 static struct seq_operations qeth_ipato_procfile_seq_ops = {
382 .start = qeth_ipato_procfile_seq_start,
383 .stop = qeth_ipato_procfile_seq_stop,
384 .next = qeth_ipato_procfile_seq_next,
385 .show = qeth_ipato_procfile_seq_show,
386 };
387
388 static int
389 qeth_ipato_procfile_open(struct inode *inode, struct file *file)
390 {
391 return seq_open(file, &qeth_ipato_procfile_seq_ops);
392 }
393
394 static struct file_operations qeth_ipato_procfile_fops = {
395 .owner = THIS_MODULE,
396 .open = qeth_ipato_procfile_open,
397 .read = seq_read,
398 .llseek = seq_lseek,
399 .release = seq_release,
400 };
401
402 int __init
403 qeth_create_procfs_entries(void)
404 {
405 qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
406 S_IFREG | 0444, NULL);
407 if (qeth_procfile)
408 qeth_procfile->proc_fops = &qeth_procfile_fops;
409
410 #ifdef CONFIG_QETH_PERF_STATS
411 qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
412 S_IFREG | 0444, NULL);
413 if (qeth_perf_procfile)
414 qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
415 #endif /* CONFIG_QETH_PERF_STATS */
416
417 qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME,
418 S_IFREG | 0444, NULL);
419 if (qeth_ipato_procfile)
420 qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops;
421
422 if (qeth_procfile &&
423 qeth_ipato_procfile &&
424 qeth_perf_procfile_created)
425 return 0;
426 else
427 return -ENOMEM;
428 }
429
430 void __exit
431 qeth_remove_procfs_entries(void)
432 {
433 if (qeth_procfile)
434 remove_proc_entry(QETH_PROCFILE_NAME, NULL);
435 if (qeth_perf_procfile)
436 remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
437 if (qeth_ipato_procfile)
438 remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL);
439 }
440
441
442 /* ONLY FOR DEVELOPMENT! -> make it as module */
443 /*
444 static void
445 qeth_create_sysfs_entries(void)
446 {
447 struct device *dev;
448
449 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
450
451 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
452 driver_list)
453 qeth_create_device_attributes(dev);
454
455 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
456 }
457
458 static void
459 qeth_remove_sysfs_entries(void)
460 {
461 struct device *dev;
462
463 down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
464
465 list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
466 driver_list)
467 qeth_remove_device_attributes(dev);
468
469 up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
470 }
471
472 static int __init
473 qeth_fs_init(void)
474 {
475 printk(KERN_INFO "qeth_fs_init\n");
476 qeth_create_procfs_entries();
477 qeth_create_sysfs_entries();
478
479 return 0;
480 }
481
482 static void __exit
483 qeth_fs_exit(void)
484 {
485 printk(KERN_INFO "qeth_fs_exit\n");
486 qeth_remove_procfs_entries();
487 qeth_remove_sysfs_entries();
488 }
489
490
491 module_init(qeth_fs_init);
492 module_exit(qeth_fs_exit);
493
494 MODULE_LICENSE("GPL");
495 */
This page took 0.058774 seconds and 6 git commands to generate.