qeth_proc.c 13 KB

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