qeth_proc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. *
  3. * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $)
  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.16 $";
  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(dev ? 1 : 0);
  30. }
  31. static void *
  32. qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
  33. {
  34. struct device *dev = NULL;
  35. loff_t nr = 0;
  36. down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  37. if (*offset == 0)
  38. return SEQ_START_TOKEN;
  39. while (1) {
  40. dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
  41. NULL, qeth_procfile_seq_match);
  42. if (++nr == *offset)
  43. break;
  44. put_device(dev);
  45. }
  46. return dev;
  47. }
  48. static void
  49. qeth_procfile_seq_stop(struct seq_file *s, void* it)
  50. {
  51. up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
  52. }
  53. static void *
  54. qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
  55. {
  56. struct device *prev, *next;
  57. if (it == SEQ_START_TOKEN)
  58. prev = NULL;
  59. else
  60. prev = (struct device *) it;
  61. next = driver_find_device(&qeth_ccwgroup_driver.driver,
  62. prev, NULL, qeth_procfile_seq_match);
  63. (*offset)++;
  64. return (void *) next;
  65. }
  66. static inline const char *
  67. qeth_get_router_str(struct qeth_card *card, int ipv)
  68. {
  69. int routing_type = 0;
  70. if (ipv == 4) {
  71. routing_type = card->options.route4.type;
  72. } else {
  73. #ifdef CONFIG_QETH_IPV6
  74. routing_type = card->options.route6.type;
  75. #else
  76. return "n/a";
  77. #endif /* CONFIG_QETH_IPV6 */
  78. }
  79. if (routing_type == PRIMARY_ROUTER)
  80. return "pri";
  81. else if (routing_type == SECONDARY_ROUTER)
  82. return "sec";
  83. else if (routing_type == MULTICAST_ROUTER) {
  84. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  85. return "mc+";
  86. return "mc";
  87. } else if (routing_type == PRIMARY_CONNECTOR) {
  88. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  89. return "p+c";
  90. return "p.c";
  91. } else if (routing_type == SECONDARY_CONNECTOR) {
  92. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  93. return "s+c";
  94. return "s.c";
  95. } else if (routing_type == NO_ROUTER)
  96. return "no";
  97. else
  98. return "unk";
  99. }
  100. static int
  101. qeth_procfile_seq_show(struct seq_file *s, void *it)
  102. {
  103. struct device *device;
  104. struct qeth_card *card;
  105. char tmp[12]; /* for qeth_get_prioq_str */
  106. if (it == SEQ_START_TOKEN){
  107. seq_printf(s, "devices CHPID interface "
  108. "cardtype port chksum prio-q'ing rtr4 "
  109. "rtr6 fsz cnt\n");
  110. seq_printf(s, "-------------------------- ----- ---------- "
  111. "-------------- ---- ------ ---------- ---- "
  112. "---- ----- -----\n");
  113. } else {
  114. device = (struct device *) it;
  115. card = device->driver_data;
  116. seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
  117. CARD_RDEV_ID(card),
  118. CARD_WDEV_ID(card),
  119. CARD_DDEV_ID(card),
  120. card->info.chpid,
  121. QETH_CARD_IFNAME(card),
  122. qeth_get_cardname_short(card),
  123. card->info.portno);
  124. if (card->lan_online)
  125. seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
  126. qeth_get_checksum_str(card),
  127. qeth_get_prioq_str(card, tmp),
  128. qeth_get_router_str(card, 4),
  129. qeth_get_router_str(card, 6),
  130. qeth_get_bufsize_str(card),
  131. card->qdio.in_buf_pool.buf_count);
  132. else
  133. seq_printf(s, " +++ LAN OFFLINE +++\n");
  134. put_device(device);
  135. }
  136. return 0;
  137. }
  138. static struct seq_operations qeth_procfile_seq_ops = {
  139. .start = qeth_procfile_seq_start,
  140. .stop = qeth_procfile_seq_stop,
  141. .next = qeth_procfile_seq_next,
  142. .show = qeth_procfile_seq_show,
  143. };
  144. static int
  145. qeth_procfile_open(struct inode *inode, struct file *file)
  146. {
  147. return seq_open(file, &qeth_procfile_seq_ops);
  148. }
  149. static struct file_operations qeth_procfile_fops = {
  150. .owner = THIS_MODULE,
  151. .open = qeth_procfile_open,
  152. .read = seq_read,
  153. .llseek = seq_lseek,
  154. .release = seq_release,
  155. };
  156. /***** /proc/qeth_perf *****/
  157. #define QETH_PERF_PROCFILE_NAME "qeth_perf"
  158. static struct proc_dir_entry *qeth_perf_procfile;
  159. #ifdef CONFIG_QETH_PERF_STATS
  160. static int
  161. qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
  162. {
  163. struct device *device;
  164. struct qeth_card *card;
  165. if (it == SEQ_START_TOKEN)
  166. return 0;
  167. device = (struct device *) it;
  168. card = device->driver_data;
  169. seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
  170. CARD_RDEV_ID(card),
  171. CARD_WDEV_ID(card),
  172. CARD_DDEV_ID(card),
  173. QETH_CARD_IFNAME(card)
  174. );
  175. seq_printf(s, " Skb's/buffers received : %li/%i\n"
  176. " Skb's/buffers sent : %li/%i\n\n",
  177. card->stats.rx_packets, card->perf_stats.bufs_rec,
  178. card->stats.tx_packets, card->perf_stats.bufs_sent
  179. );
  180. seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n"
  181. " Skb's/buffers sent with packing : %i/%i\n\n",
  182. card->stats.tx_packets - card->perf_stats.skbs_sent_pack,
  183. card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
  184. card->perf_stats.skbs_sent_pack,
  185. card->perf_stats.bufs_sent_pack
  186. );
  187. seq_printf(s, " Skbs sent in SG mode : %i\n"
  188. " Skb fragments sent in SG mode : %i\n\n",
  189. card->perf_stats.sg_skbs_sent,
  190. card->perf_stats.sg_frags_sent);
  191. seq_printf(s, " large_send tx (in Kbytes) : %i\n"
  192. " large_send count : %i\n\n",
  193. card->perf_stats.large_send_bytes >> 10,
  194. card->perf_stats.large_send_cnt);
  195. seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
  196. " Watermarks L/H : %i/%i\n"
  197. " Current buffer usage (outbound q's) : "
  198. "%i/%i/%i/%i\n\n",
  199. card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
  200. QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
  201. atomic_read(&card->qdio.out_qs[0]->used_buffers),
  202. (card->qdio.no_out_queues > 1)?
  203. atomic_read(&card->qdio.out_qs[1]->used_buffers)
  204. : 0,
  205. (card->qdio.no_out_queues > 2)?
  206. atomic_read(&card->qdio.out_qs[2]->used_buffers)
  207. : 0,
  208. (card->qdio.no_out_queues > 3)?
  209. atomic_read(&card->qdio.out_qs[3]->used_buffers)
  210. : 0
  211. );
  212. seq_printf(s, " Inbound handler time (in us) : %i\n"
  213. " Inbound handler count : %i\n"
  214. " Inbound do_QDIO time (in us) : %i\n"
  215. " Inbound do_QDIO count : %i\n\n"
  216. " Outbound handler time (in us) : %i\n"
  217. " Outbound handler count : %i\n\n"
  218. " Outbound time (in us, incl QDIO) : %i\n"
  219. " Outbound count : %i\n"
  220. " Outbound do_QDIO time (in us) : %i\n"
  221. " Outbound do_QDIO count : %i\n\n",
  222. card->perf_stats.inbound_time,
  223. card->perf_stats.inbound_cnt,
  224. card->perf_stats.inbound_do_qdio_time,
  225. card->perf_stats.inbound_do_qdio_cnt,
  226. card->perf_stats.outbound_handler_time,
  227. card->perf_stats.outbound_handler_cnt,
  228. card->perf_stats.outbound_time,
  229. card->perf_stats.outbound_cnt,
  230. card->perf_stats.outbound_do_qdio_time,
  231. card->perf_stats.outbound_do_qdio_cnt
  232. );
  233. put_device(device);
  234. return 0;
  235. }
  236. static struct seq_operations qeth_perf_procfile_seq_ops = {
  237. .start = qeth_procfile_seq_start,
  238. .stop = qeth_procfile_seq_stop,
  239. .next = qeth_procfile_seq_next,
  240. .show = qeth_perf_procfile_seq_show,
  241. };
  242. static int
  243. qeth_perf_procfile_open(struct inode *inode, struct file *file)
  244. {
  245. return seq_open(file, &qeth_perf_procfile_seq_ops);
  246. }
  247. static struct file_operations qeth_perf_procfile_fops = {
  248. .owner = THIS_MODULE,
  249. .open = qeth_perf_procfile_open,
  250. .read = seq_read,
  251. .llseek = seq_lseek,
  252. .release = seq_release,
  253. };
  254. #define qeth_perf_procfile_created qeth_perf_procfile
  255. #else
  256. #define qeth_perf_procfile_created 1
  257. #endif /* CONFIG_QETH_PERF_STATS */
  258. int __init
  259. qeth_create_procfs_entries(void)
  260. {
  261. qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
  262. S_IFREG | 0444, NULL);
  263. if (qeth_procfile)
  264. qeth_procfile->proc_fops = &qeth_procfile_fops;
  265. #ifdef CONFIG_QETH_PERF_STATS
  266. qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
  267. S_IFREG | 0444, NULL);
  268. if (qeth_perf_procfile)
  269. qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
  270. #endif /* CONFIG_QETH_PERF_STATS */
  271. if (qeth_procfile &&
  272. qeth_perf_procfile_created)
  273. return 0;
  274. else
  275. return -ENOMEM;
  276. }
  277. void __exit
  278. qeth_remove_procfs_entries(void)
  279. {
  280. if (qeth_procfile)
  281. remove_proc_entry(QETH_PROCFILE_NAME, NULL);
  282. if (qeth_perf_procfile)
  283. remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
  284. }