snic_debugfs.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * Copyright 2014 Cisco Systems, Inc. All rights reserved.
  3. *
  4. * This program is free software; you may redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; version 2 of the License.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  9. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  10. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  11. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  12. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  13. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  14. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  15. * SOFTWARE.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/errno.h>
  19. #include <linux/debugfs.h>
  20. #include "snic.h"
  21. /*
  22. * snic_debugfs_init - Initialize debugfs for snic debug logging
  23. *
  24. * Description:
  25. * When Debugfs is configured this routine sets up fnic debugfs
  26. * filesystem. If not already created. this routine will crate the
  27. * fnic directory and statistics directory for trace buffer and
  28. * stats logging
  29. */
  30. void snic_debugfs_init(void)
  31. {
  32. snic_glob->trc_root = debugfs_create_dir("snic", NULL);
  33. snic_glob->stats_root = debugfs_create_dir("statistics",
  34. snic_glob->trc_root);
  35. }
  36. /*
  37. * snic_debugfs_term - Tear down debugfs intrastructure
  38. *
  39. * Description:
  40. * When Debufs is configured this routine removes debugfs file system
  41. * elements that are specific to snic
  42. */
  43. void
  44. snic_debugfs_term(void)
  45. {
  46. debugfs_remove(snic_glob->stats_root);
  47. snic_glob->stats_root = NULL;
  48. debugfs_remove(snic_glob->trc_root);
  49. snic_glob->trc_root = NULL;
  50. }
  51. /*
  52. * snic_reset_stats_open - Open the reset_stats file
  53. */
  54. static int
  55. snic_reset_stats_open(struct inode *inode, struct file *filp)
  56. {
  57. SNIC_BUG_ON(!inode->i_private);
  58. filp->private_data = inode->i_private;
  59. return 0;
  60. }
  61. /*
  62. * snic_reset_stats_read - Read a reset_stats debugfs file
  63. * @filp: The file pointer to read from.
  64. * @ubuf: The buffer tocopy the data to.
  65. * @cnt: The number of bytes to read.
  66. * @ppos: The position in the file to start reading frm.
  67. *
  68. * Description:
  69. * This routine reads value of variable reset_stats
  70. * and stores into local @buf. It will start reading file @ppos and
  71. * copy up to @cnt of data to @ubuf from @buf.
  72. *
  73. * Returns:
  74. * This function returns the amount of data that was read.
  75. */
  76. static ssize_t
  77. snic_reset_stats_read(struct file *filp,
  78. char __user *ubuf,
  79. size_t cnt,
  80. loff_t *ppos)
  81. {
  82. struct snic *snic = (struct snic *) filp->private_data;
  83. char buf[64];
  84. int len;
  85. len = sprintf(buf, "%u\n", snic->reset_stats);
  86. return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
  87. }
  88. /*
  89. * snic_reset_stats_write - Write to reset_stats debugfs file
  90. * @filp: The file pointer to write from
  91. * @ubuf: The buffer to copy the data from.
  92. * @cnt: The number of bytes to write.
  93. * @ppos: The position in the file to start writing to.
  94. *
  95. * Description:
  96. * This routine writes data from user buffer @ubuf to buffer @buf and
  97. * resets cumulative stats of snic.
  98. *
  99. * Returns:
  100. * This function returns the amount of data that was written.
  101. */
  102. static ssize_t
  103. snic_reset_stats_write(struct file *filp,
  104. const char __user *ubuf,
  105. size_t cnt,
  106. loff_t *ppos)
  107. {
  108. struct snic *snic = (struct snic *) filp->private_data;
  109. struct snic_stats *stats = &snic->s_stats;
  110. u64 *io_stats_p = (u64 *) &stats->io;
  111. u64 *fw_stats_p = (u64 *) &stats->fw;
  112. char buf[64];
  113. unsigned long val;
  114. int ret;
  115. if (cnt >= sizeof(buf))
  116. return -EINVAL;
  117. if (copy_from_user(&buf, ubuf, cnt))
  118. return -EFAULT;
  119. buf[cnt] = '\0';
  120. ret = kstrtoul(buf, 10, &val);
  121. if (ret < 0)
  122. return ret;
  123. snic->reset_stats = val;
  124. if (snic->reset_stats) {
  125. /* Skip variable is used to avoid descrepancies to Num IOs
  126. * and IO Completions stats. Skip incrementing No IO Compls
  127. * for pending active IOs after reset_stats
  128. */
  129. atomic64_set(&snic->io_cmpl_skip,
  130. atomic64_read(&stats->io.active));
  131. memset(&stats->abts, 0, sizeof(struct snic_abort_stats));
  132. memset(&stats->reset, 0, sizeof(struct snic_reset_stats));
  133. memset(&stats->misc, 0, sizeof(struct snic_misc_stats));
  134. memset(io_stats_p+1,
  135. 0,
  136. sizeof(struct snic_io_stats) - sizeof(u64));
  137. memset(fw_stats_p+1,
  138. 0,
  139. sizeof(struct snic_fw_stats) - sizeof(u64));
  140. }
  141. (*ppos)++;
  142. SNIC_HOST_INFO(snic->shost, "Reset Op: Driver statistics.\n");
  143. return cnt;
  144. }
  145. static int
  146. snic_reset_stats_release(struct inode *inode, struct file *filp)
  147. {
  148. filp->private_data = NULL;
  149. return 0;
  150. }
  151. /*
  152. * snic_stats_show - Formats and prints per host specific driver stats.
  153. */
  154. static int
  155. snic_stats_show(struct seq_file *sfp, void *data)
  156. {
  157. struct snic *snic = (struct snic *) sfp->private;
  158. struct snic_stats *stats = &snic->s_stats;
  159. struct timespec64 last_isr_tms, last_ack_tms;
  160. u64 maxio_tm;
  161. int i;
  162. /* Dump IO Stats */
  163. seq_printf(sfp,
  164. "------------------------------------------\n"
  165. "\t\t IO Statistics\n"
  166. "------------------------------------------\n");
  167. maxio_tm = (u64) atomic64_read(&stats->io.max_time);
  168. seq_printf(sfp,
  169. "Active IOs : %lld\n"
  170. "Max Active IOs : %lld\n"
  171. "Total IOs : %lld\n"
  172. "IOs Completed : %lld\n"
  173. "IOs Failed : %lld\n"
  174. "IOs Not Found : %lld\n"
  175. "Memory Alloc Failures : %lld\n"
  176. "REQs Null : %lld\n"
  177. "SCSI Cmd Pointers Null : %lld\n"
  178. "Max SGL for any IO : %lld\n"
  179. "Max IO Size : %lld Sectors\n"
  180. "Max Queuing Time : %lld\n"
  181. "Max Completion Time : %lld\n"
  182. "Max IO Process Time(FW) : %lld (%u msec)\n",
  183. (u64) atomic64_read(&stats->io.active),
  184. (u64) atomic64_read(&stats->io.max_active),
  185. (u64) atomic64_read(&stats->io.num_ios),
  186. (u64) atomic64_read(&stats->io.compl),
  187. (u64) atomic64_read(&stats->io.fail),
  188. (u64) atomic64_read(&stats->io.io_not_found),
  189. (u64) atomic64_read(&stats->io.alloc_fail),
  190. (u64) atomic64_read(&stats->io.req_null),
  191. (u64) atomic64_read(&stats->io.sc_null),
  192. (u64) atomic64_read(&stats->io.max_sgl),
  193. (u64) atomic64_read(&stats->io.max_io_sz),
  194. (u64) atomic64_read(&stats->io.max_qtime),
  195. (u64) atomic64_read(&stats->io.max_cmpl_time),
  196. maxio_tm,
  197. jiffies_to_msecs(maxio_tm));
  198. seq_puts(sfp, "\nSGL Counters\n");
  199. for (i = 0; i < SNIC_MAX_SG_DESC_CNT; i++) {
  200. seq_printf(sfp,
  201. "%10lld ",
  202. (u64) atomic64_read(&stats->io.sgl_cnt[i]));
  203. if ((i + 1) % 8 == 0)
  204. seq_puts(sfp, "\n");
  205. }
  206. /* Dump Abort Stats */
  207. seq_printf(sfp,
  208. "\n-------------------------------------------\n"
  209. "\t\t Abort Statistics\n"
  210. "---------------------------------------------\n");
  211. seq_printf(sfp,
  212. "Aborts : %lld\n"
  213. "Aborts Fail : %lld\n"
  214. "Aborts Driver Timeout : %lld\n"
  215. "Abort FW Timeout : %lld\n"
  216. "Abort IO NOT Found : %lld\n"
  217. "Abort Queuing Failed : %lld\n",
  218. (u64) atomic64_read(&stats->abts.num),
  219. (u64) atomic64_read(&stats->abts.fail),
  220. (u64) atomic64_read(&stats->abts.drv_tmo),
  221. (u64) atomic64_read(&stats->abts.fw_tmo),
  222. (u64) atomic64_read(&stats->abts.io_not_found),
  223. (u64) atomic64_read(&stats->abts.q_fail));
  224. /* Dump Reset Stats */
  225. seq_printf(sfp,
  226. "\n-------------------------------------------\n"
  227. "\t\t Reset Statistics\n"
  228. "---------------------------------------------\n");
  229. seq_printf(sfp,
  230. "HBA Resets : %lld\n"
  231. "HBA Reset Cmpls : %lld\n"
  232. "HBA Reset Fail : %lld\n",
  233. (u64) atomic64_read(&stats->reset.hba_resets),
  234. (u64) atomic64_read(&stats->reset.hba_reset_cmpl),
  235. (u64) atomic64_read(&stats->reset.hba_reset_fail));
  236. /* Dump Firmware Stats */
  237. seq_printf(sfp,
  238. "\n-------------------------------------------\n"
  239. "\t\t Firmware Statistics\n"
  240. "---------------------------------------------\n");
  241. seq_printf(sfp,
  242. "Active FW Requests : %lld\n"
  243. "Max FW Requests : %lld\n"
  244. "FW Out Of Resource Errs : %lld\n"
  245. "FW IO Errors : %lld\n"
  246. "FW SCSI Errors : %lld\n",
  247. (u64) atomic64_read(&stats->fw.actv_reqs),
  248. (u64) atomic64_read(&stats->fw.max_actv_reqs),
  249. (u64) atomic64_read(&stats->fw.out_of_res),
  250. (u64) atomic64_read(&stats->fw.io_errs),
  251. (u64) atomic64_read(&stats->fw.scsi_errs));
  252. /* Dump Miscellenous Stats */
  253. seq_printf(sfp,
  254. "\n---------------------------------------------\n"
  255. "\t\t Other Statistics\n"
  256. "\n---------------------------------------------\n");
  257. jiffies_to_timespec64(stats->misc.last_isr_time, &last_isr_tms);
  258. jiffies_to_timespec64(stats->misc.last_ack_time, &last_ack_tms);
  259. seq_printf(sfp,
  260. "Last ISR Time : %llu (%8llu.%09lu)\n"
  261. "Last Ack Time : %llu (%8llu.%09lu)\n"
  262. "Ack ISRs : %llu\n"
  263. "IO Cmpl ISRs : %llu\n"
  264. "Err Notify ISRs : %llu\n"
  265. "Max CQ Entries : %lld\n"
  266. "Data Count Mismatch : %lld\n"
  267. "IOs w/ Timeout Status : %lld\n"
  268. "IOs w/ Aborted Status : %lld\n"
  269. "IOs w/ SGL Invalid Stat : %lld\n"
  270. "WQ Desc Alloc Fail : %lld\n"
  271. "Queue Full : %lld\n"
  272. "Queue Ramp Up : %lld\n"
  273. "Queue Ramp Down : %lld\n"
  274. "Queue Last Queue Depth : %lld\n"
  275. "Target Not Ready : %lld\n",
  276. (u64) stats->misc.last_isr_time,
  277. last_isr_tms.tv_sec, last_isr_tms.tv_nsec,
  278. (u64)stats->misc.last_ack_time,
  279. last_ack_tms.tv_sec, last_ack_tms.tv_nsec,
  280. (u64) atomic64_read(&stats->misc.ack_isr_cnt),
  281. (u64) atomic64_read(&stats->misc.cmpl_isr_cnt),
  282. (u64) atomic64_read(&stats->misc.errnotify_isr_cnt),
  283. (u64) atomic64_read(&stats->misc.max_cq_ents),
  284. (u64) atomic64_read(&stats->misc.data_cnt_mismat),
  285. (u64) atomic64_read(&stats->misc.io_tmo),
  286. (u64) atomic64_read(&stats->misc.io_aborted),
  287. (u64) atomic64_read(&stats->misc.sgl_inval),
  288. (u64) atomic64_read(&stats->misc.wq_alloc_fail),
  289. (u64) atomic64_read(&stats->misc.qfull),
  290. (u64) atomic64_read(&stats->misc.qsz_rampup),
  291. (u64) atomic64_read(&stats->misc.qsz_rampdown),
  292. (u64) atomic64_read(&stats->misc.last_qsz),
  293. (u64) atomic64_read(&stats->misc.tgt_not_rdy));
  294. return 0;
  295. }
  296. /*
  297. * snic_stats_open - Open the stats file for specific host
  298. *
  299. * Description:
  300. * This routine opens a debugfs file stats of specific host
  301. */
  302. static int
  303. snic_stats_open(struct inode *inode, struct file *filp)
  304. {
  305. return single_open(filp, snic_stats_show, inode->i_private);
  306. }
  307. static const struct file_operations snic_stats_fops = {
  308. .owner = THIS_MODULE,
  309. .open = snic_stats_open,
  310. .read = seq_read,
  311. .llseek = seq_lseek,
  312. .release = single_release,
  313. };
  314. static const struct file_operations snic_reset_stats_fops = {
  315. .owner = THIS_MODULE,
  316. .open = snic_reset_stats_open,
  317. .read = snic_reset_stats_read,
  318. .write = snic_reset_stats_write,
  319. .release = snic_reset_stats_release,
  320. };
  321. /*
  322. * snic_stats_init - Initialize stats struct and create stats file
  323. * per snic
  324. *
  325. * Description:
  326. * When debugfs is cofigured this routine sets up the stats file per snic
  327. * It will create file stats and reset_stats under statistics/host# directory
  328. * to log per snic stats
  329. */
  330. void snic_stats_debugfs_init(struct snic *snic)
  331. {
  332. char name[16];
  333. snprintf(name, sizeof(name), "host%d", snic->shost->host_no);
  334. snic->stats_host = debugfs_create_dir(name, snic_glob->stats_root);
  335. snic->stats_file = debugfs_create_file("stats", S_IFREG|S_IRUGO,
  336. snic->stats_host, snic,
  337. &snic_stats_fops);
  338. snic->reset_stats_file = debugfs_create_file("reset_stats",
  339. S_IFREG|S_IRUGO|S_IWUSR,
  340. snic->stats_host, snic,
  341. &snic_reset_stats_fops);
  342. }
  343. /*
  344. * snic_stats_debugfs_remove - Tear down debugfs infrastructure of stats
  345. *
  346. * Description:
  347. * When Debufs is configured this routine removes debugfs file system
  348. * elements that are specific to to snic stats
  349. */
  350. void
  351. snic_stats_debugfs_remove(struct snic *snic)
  352. {
  353. debugfs_remove(snic->stats_file);
  354. snic->stats_file = NULL;
  355. debugfs_remove(snic->reset_stats_file);
  356. snic->reset_stats_file = NULL;
  357. debugfs_remove(snic->stats_host);
  358. snic->stats_host = NULL;
  359. }
  360. /* Trace Facility related API */
  361. static void *
  362. snic_trc_seq_start(struct seq_file *sfp, loff_t *pos)
  363. {
  364. return &snic_glob->trc;
  365. }
  366. static void *
  367. snic_trc_seq_next(struct seq_file *sfp, void *data, loff_t *pos)
  368. {
  369. return NULL;
  370. }
  371. static void
  372. snic_trc_seq_stop(struct seq_file *sfp, void *data)
  373. {
  374. }
  375. #define SNIC_TRC_PBLEN 256
  376. static int
  377. snic_trc_seq_show(struct seq_file *sfp, void *data)
  378. {
  379. char buf[SNIC_TRC_PBLEN];
  380. if (snic_get_trc_data(buf, SNIC_TRC_PBLEN) > 0)
  381. seq_printf(sfp, "%s\n", buf);
  382. return 0;
  383. }
  384. static const struct seq_operations snic_trc_sops = {
  385. .start = snic_trc_seq_start,
  386. .next = snic_trc_seq_next,
  387. .stop = snic_trc_seq_stop,
  388. .show = snic_trc_seq_show,
  389. };
  390. DEFINE_SEQ_ATTRIBUTE(snic_trc);
  391. /*
  392. * snic_trc_debugfs_init : creates trace/tracing_enable files for trace
  393. * under debugfs
  394. */
  395. void snic_trc_debugfs_init(void)
  396. {
  397. snic_glob->trc.trc_enable = debugfs_create_bool("tracing_enable",
  398. S_IFREG | S_IRUGO | S_IWUSR,
  399. snic_glob->trc_root,
  400. &snic_glob->trc.enable);
  401. snic_glob->trc.trc_file = debugfs_create_file("trace",
  402. S_IFREG | S_IRUGO | S_IWUSR,
  403. snic_glob->trc_root, NULL,
  404. &snic_trc_fops);
  405. }
  406. /*
  407. * snic_trc_debugfs_term : cleans up the files created for trace under debugfs
  408. */
  409. void
  410. snic_trc_debugfs_term(void)
  411. {
  412. debugfs_remove(snic_glob->trc.trc_file);
  413. snic_glob->trc.trc_file = NULL;
  414. debugfs_remove(snic_glob->trc.trc_enable);
  415. snic_glob->trc.trc_enable = NULL;
  416. }