qeth_proc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  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. #include "qeth.h"
  20. #include "qeth_mpc.h"
  21. #include "qeth_fs.h"
  22. const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
  23. /***** /proc/qeth *****/
  24. #define QETH_PROCFILE_NAME "qeth"
  25. static struct proc_dir_entry *qeth_procfile;
  26. static void *
  27. qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
  28. {
  29. struct list_head *next_card = NULL;
  30. int i = 0;
  31. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  32. if (*offset == 0)
  33. return SEQ_START_TOKEN;
  34. /* get card at pos *offset */
  35. list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
  36. if (++i == *offset)
  37. return next_card;
  38. return NULL;
  39. }
  40. static void
  41. qeth_procfile_seq_stop(struct seq_file *s, void* it)
  42. {
  43. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  44. }
  45. static void *
  46. qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
  47. {
  48. struct list_head *next_card = NULL;
  49. struct list_head *current_card;
  50. if (it == SEQ_START_TOKEN) {
  51. next_card = qeth_ccwgroup_driver.driver.devices.next;
  52. if (next_card->next == next_card) /* list empty */
  53. return NULL;
  54. (*offset)++;
  55. } else {
  56. current_card = (struct list_head *)it;
  57. if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
  58. return NULL; /* end of list reached */
  59. next_card = current_card->next;
  60. (*offset)++;
  61. }
  62. return next_card;
  63. }
  64. static inline const char *
  65. qeth_get_router_str(struct qeth_card *card, int ipv)
  66. {
  67. int routing_type = 0;
  68. if (ipv == 4){
  69. routing_type = card->options.route4.type;
  70. } else {
  71. #ifdef CONFIG_QETH_IPV6
  72. routing_type = card->options.route6.type;
  73. #else
  74. return "n/a";
  75. #endif /* CONFIG_QETH_IPV6 */
  76. }
  77. if (routing_type == PRIMARY_ROUTER)
  78. return "pri";
  79. else if (routing_type == SECONDARY_ROUTER)
  80. return "sec";
  81. else if (routing_type == MULTICAST_ROUTER) {
  82. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  83. return "mc+";
  84. return "mc";
  85. } else if (routing_type == PRIMARY_CONNECTOR) {
  86. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  87. return "p+c";
  88. return "p.c";
  89. } else if (routing_type == SECONDARY_CONNECTOR) {
  90. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  91. return "s+c";
  92. return "s.c";
  93. } else if (routing_type == NO_ROUTER)
  94. return "no";
  95. else
  96. return "unk";
  97. }
  98. static int
  99. qeth_procfile_seq_show(struct seq_file *s, void *it)
  100. {
  101. struct device *device;
  102. struct qeth_card *card;
  103. char tmp[12]; /* for qeth_get_prioq_str */
  104. if (it == SEQ_START_TOKEN){
  105. seq_printf(s, "devices CHPID interface "
  106. "cardtype port chksum prio-q'ing rtr4 "
  107. "rtr6 fsz cnt\n");
  108. seq_printf(s, "-------------------------- ----- ---------- "
  109. "-------------- ---- ------ ---------- ---- "
  110. "---- ----- -----\n");
  111. } else {
  112. device = list_entry(it, struct device, driver_list);
  113. card = device->driver_data;
  114. seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
  115. CARD_RDEV_ID(card),
  116. CARD_WDEV_ID(card),
  117. CARD_DDEV_ID(card),
  118. card->info.chpid,
  119. QETH_CARD_IFNAME(card),
  120. qeth_get_cardname_short(card),
  121. card->info.portno);
  122. if (card->lan_online)
  123. seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
  124. qeth_get_checksum_str(card),
  125. qeth_get_prioq_str(card, tmp),
  126. qeth_get_router_str(card, 4),
  127. qeth_get_router_str(card, 6),
  128. qeth_get_bufsize_str(card),
  129. card->qdio.in_buf_pool.buf_count);
  130. else
  131. seq_printf(s, " +++ LAN OFFLINE +++\n");
  132. }
  133. return 0;
  134. }
  135. static struct seq_operations qeth_procfile_seq_ops = {
  136. .start = qeth_procfile_seq_start,
  137. .stop = qeth_procfile_seq_stop,
  138. .next = qeth_procfile_seq_next,
  139. .show = qeth_procfile_seq_show,
  140. };
  141. static int
  142. qeth_procfile_open(struct inode *inode, struct file *file)
  143. {
  144. return seq_open(file, &qeth_procfile_seq_ops);
  145. }
  146. static struct file_operations qeth_procfile_fops = {
  147. .owner = THIS_MODULE,
  148. .open = qeth_procfile_open,
  149. .read = seq_read,
  150. .llseek = seq_lseek,
  151. .release = seq_release,
  152. };
  153. /***** /proc/qeth_perf *****/
  154. #define QETH_PERF_PROCFILE_NAME "qeth_perf"
  155. static struct proc_dir_entry *qeth_perf_procfile;
  156. #ifdef CONFIG_QETH_PERF_STATS
  157. static void *
  158. qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
  159. {
  160. struct list_head *next_card = NULL;
  161. int i = 0;
  162. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  163. /* get card at pos *offset */
  164. list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
  165. if (i == *offset)
  166. return next_card;
  167. i++;
  168. }
  169. return NULL;
  170. }
  171. static void
  172. qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
  173. {
  174. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  175. }
  176. static void *
  177. qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
  178. {
  179. struct list_head *current_card = (struct list_head *)it;
  180. if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
  181. return NULL; /* end of list reached */
  182. (*offset)++;
  183. return current_card->next;
  184. }
  185. static int
  186. qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
  187. {
  188. struct device *device;
  189. struct qeth_card *card;
  190. device = list_entry(it, struct device, driver_list);
  191. card = device->driver_data;
  192. seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
  193. CARD_RDEV_ID(card),
  194. CARD_WDEV_ID(card),
  195. CARD_DDEV_ID(card),
  196. QETH_CARD_IFNAME(card)
  197. );
  198. seq_printf(s, " Skb's/buffers received : %li/%i\n"
  199. " Skb's/buffers sent : %li/%i\n\n",
  200. card->stats.rx_packets, card->perf_stats.bufs_rec,
  201. card->stats.tx_packets, card->perf_stats.bufs_sent
  202. );
  203. seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n"
  204. " Skb's/buffers sent with packing : %i/%i\n\n",
  205. card->stats.tx_packets - card->perf_stats.skbs_sent_pack,
  206. card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
  207. card->perf_stats.skbs_sent_pack,
  208. card->perf_stats.bufs_sent_pack
  209. );
  210. seq_printf(s, " Skbs sent in SG mode : %i\n"
  211. " Skb fragments sent in SG mode : %i\n\n",
  212. card->perf_stats.sg_skbs_sent,
  213. card->perf_stats.sg_frags_sent);
  214. seq_printf(s, " large_send tx (in Kbytes) : %i\n"
  215. " large_send count : %i\n\n",
  216. card->perf_stats.large_send_bytes >> 10,
  217. card->perf_stats.large_send_cnt);
  218. seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
  219. " Watermarks L/H : %i/%i\n"
  220. " Current buffer usage (outbound q's) : "
  221. "%i/%i/%i/%i\n\n",
  222. card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
  223. QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
  224. atomic_read(&card->qdio.out_qs[0]->used_buffers),
  225. (card->qdio.no_out_queues > 1)?
  226. atomic_read(&card->qdio.out_qs[1]->used_buffers)
  227. : 0,
  228. (card->qdio.no_out_queues > 2)?
  229. atomic_read(&card->qdio.out_qs[2]->used_buffers)
  230. : 0,
  231. (card->qdio.no_out_queues > 3)?
  232. atomic_read(&card->qdio.out_qs[3]->used_buffers)
  233. : 0
  234. );
  235. seq_printf(s, " Inbound handler time (in us) : %i\n"
  236. " Inbound handler count : %i\n"
  237. " Inbound do_QDIO time (in us) : %i\n"
  238. " Inbound do_QDIO count : %i\n\n"
  239. " Outbound handler time (in us) : %i\n"
  240. " Outbound handler count : %i\n\n"
  241. " Outbound time (in us, incl QDIO) : %i\n"
  242. " Outbound count : %i\n"
  243. " Outbound do_QDIO time (in us) : %i\n"
  244. " Outbound do_QDIO count : %i\n\n",
  245. card->perf_stats.inbound_time,
  246. card->perf_stats.inbound_cnt,
  247. card->perf_stats.inbound_do_qdio_time,
  248. card->perf_stats.inbound_do_qdio_cnt,
  249. card->perf_stats.outbound_handler_time,
  250. card->perf_stats.outbound_handler_cnt,
  251. card->perf_stats.outbound_time,
  252. card->perf_stats.outbound_cnt,
  253. card->perf_stats.outbound_do_qdio_time,
  254. card->perf_stats.outbound_do_qdio_cnt
  255. );
  256. return 0;
  257. }
  258. static struct seq_operations qeth_perf_procfile_seq_ops = {
  259. .start = qeth_perf_procfile_seq_start,
  260. .stop = qeth_perf_procfile_seq_stop,
  261. .next = qeth_perf_procfile_seq_next,
  262. .show = qeth_perf_procfile_seq_show,
  263. };
  264. static int
  265. qeth_perf_procfile_open(struct inode *inode, struct file *file)
  266. {
  267. return seq_open(file, &qeth_perf_procfile_seq_ops);
  268. }
  269. static struct file_operations qeth_perf_procfile_fops = {
  270. .owner = THIS_MODULE,
  271. .open = qeth_perf_procfile_open,
  272. .read = seq_read,
  273. .llseek = seq_lseek,
  274. .release = seq_release,
  275. };
  276. #define qeth_perf_procfile_created qeth_perf_procfile
  277. #else
  278. #define qeth_perf_procfile_created 1
  279. #endif /* CONFIG_QETH_PERF_STATS */
  280. /***** /proc/qeth_ipa_takeover *****/
  281. #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover"
  282. static struct proc_dir_entry *qeth_ipato_procfile;
  283. static void *
  284. qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
  285. {
  286. struct list_head *next_card = NULL;
  287. int i = 0;
  288. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  289. /* TODO: finish this */
  290. /*
  291. * maybe SEQ_SATRT_TOKEN can be returned for offset 0
  292. * output driver settings then;
  293. * else output setting for respective card
  294. */
  295. /* get card at pos *offset */
  296. list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
  297. if (i == *offset)
  298. return next_card;
  299. i++;
  300. }
  301. return NULL;
  302. }
  303. static void
  304. qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
  305. {
  306. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  307. }
  308. static void *
  309. qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
  310. {
  311. struct list_head *current_card = (struct list_head *)it;
  312. /* TODO: finish this */
  313. /*
  314. * maybe SEQ_SATRT_TOKEN can be returned for offset 0
  315. * output driver settings then;
  316. * else output setting for respective card
  317. */
  318. if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
  319. return NULL; /* end of list reached */
  320. (*offset)++;
  321. return current_card->next;
  322. }
  323. static int
  324. qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
  325. {
  326. struct device *device;
  327. struct qeth_card *card;
  328. /* TODO: finish this */
  329. /*
  330. * maybe SEQ_SATRT_TOKEN can be returned for offset 0
  331. * output driver settings then;
  332. * else output setting for respective card
  333. */
  334. device = list_entry(it, struct device, driver_list);
  335. card = device->driver_data;
  336. return 0;
  337. }
  338. static struct seq_operations qeth_ipato_procfile_seq_ops = {
  339. .start = qeth_ipato_procfile_seq_start,
  340. .stop = qeth_ipato_procfile_seq_stop,
  341. .next = qeth_ipato_procfile_seq_next,
  342. .show = qeth_ipato_procfile_seq_show,
  343. };
  344. static int
  345. qeth_ipato_procfile_open(struct inode *inode, struct file *file)
  346. {
  347. return seq_open(file, &qeth_ipato_procfile_seq_ops);
  348. }
  349. static struct file_operations qeth_ipato_procfile_fops = {
  350. .owner = THIS_MODULE,
  351. .open = qeth_ipato_procfile_open,
  352. .read = seq_read,
  353. .llseek = seq_lseek,
  354. .release = seq_release,
  355. };
  356. int __init
  357. qeth_create_procfs_entries(void)
  358. {
  359. qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
  360. S_IFREG | 0444, NULL);
  361. if (qeth_procfile)
  362. qeth_procfile->proc_fops = &qeth_procfile_fops;
  363. #ifdef CONFIG_QETH_PERF_STATS
  364. qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
  365. S_IFREG | 0444, NULL);
  366. if (qeth_perf_procfile)
  367. qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
  368. #endif /* CONFIG_QETH_PERF_STATS */
  369. qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME,
  370. S_IFREG | 0444, NULL);
  371. if (qeth_ipato_procfile)
  372. qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops;
  373. if (qeth_procfile &&
  374. qeth_ipato_procfile &&
  375. qeth_perf_procfile_created)
  376. return 0;
  377. else
  378. return -ENOMEM;
  379. }
  380. void __exit
  381. qeth_remove_procfs_entries(void)
  382. {
  383. if (qeth_procfile)
  384. remove_proc_entry(QETH_PROCFILE_NAME, NULL);
  385. if (qeth_perf_procfile)
  386. remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
  387. if (qeth_ipato_procfile)
  388. remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL);
  389. }
  390. /* ONLY FOR DEVELOPMENT! -> make it as module */
  391. /*
  392. static void
  393. qeth_create_sysfs_entries(void)
  394. {
  395. struct device *dev;
  396. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  397. list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
  398. driver_list)
  399. qeth_create_device_attributes(dev);
  400. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  401. }
  402. static void
  403. qeth_remove_sysfs_entries(void)
  404. {
  405. struct device *dev;
  406. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  407. list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices,
  408. driver_list)
  409. qeth_remove_device_attributes(dev);
  410. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  411. }
  412. static int __init
  413. qeth_fs_init(void)
  414. {
  415. printk(KERN_INFO "qeth_fs_init\n");
  416. qeth_create_procfs_entries();
  417. qeth_create_sysfs_entries();
  418. return 0;
  419. }
  420. static void __exit
  421. qeth_fs_exit(void)
  422. {
  423. printk(KERN_INFO "qeth_fs_exit\n");
  424. qeth_remove_procfs_entries();
  425. qeth_remove_sysfs_entries();
  426. }
  427. module_init(qeth_fs_init);
  428. module_exit(qeth_fs_exit);
  429. MODULE_LICENSE("GPL");
  430. */