fnic_trace.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright 2012 Cisco Systems, Inc. All rights reserved.
  3. #include <linux/module.h>
  4. #include <linux/mempool.h>
  5. #include <linux/errno.h>
  6. #include <linux/spinlock.h>
  7. #include <linux/kallsyms.h>
  8. #include <linux/time.h>
  9. #include <linux/vmalloc.h>
  10. #include "fnic_io.h"
  11. #include "fnic.h"
  12. unsigned int trace_max_pages;
  13. static int fnic_max_trace_entries;
  14. static unsigned long fnic_trace_buf_p;
  15. static DEFINE_SPINLOCK(fnic_trace_lock);
  16. static fnic_trace_dbg_t fnic_trace_entries;
  17. int fnic_tracing_enabled = 1;
  18. /* static char *fnic_fc_ctlr_trace_buf_p; */
  19. static int fc_trace_max_entries;
  20. static unsigned long fnic_fc_ctlr_trace_buf_p;
  21. static fnic_trace_dbg_t fc_trace_entries;
  22. int fnic_fc_tracing_enabled = 1;
  23. int fnic_fc_trace_cleared = 1;
  24. static DEFINE_SPINLOCK(fnic_fc_trace_lock);
  25. /*
  26. * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
  27. *
  28. * Description:
  29. * This routine gets next available trace buffer entry location @wr_idx
  30. * from allocated trace buffer pages and give that memory location
  31. * to user to store the trace information.
  32. *
  33. * Return Value:
  34. * This routine returns pointer to next available trace entry
  35. * @fnic_buf_head for user to fill trace information.
  36. */
  37. fnic_trace_data_t *fnic_trace_get_buf(void)
  38. {
  39. unsigned long fnic_buf_head;
  40. unsigned long flags;
  41. spin_lock_irqsave(&fnic_trace_lock, flags);
  42. /*
  43. * Get next available memory location for writing trace information
  44. * at @wr_idx and increment @wr_idx
  45. */
  46. fnic_buf_head =
  47. fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx];
  48. fnic_trace_entries.wr_idx++;
  49. /*
  50. * Verify if trace buffer is full then change wd_idx to
  51. * start from zero
  52. */
  53. if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries)
  54. fnic_trace_entries.wr_idx = 0;
  55. /*
  56. * Verify if write index @wr_idx and read index @rd_idx are same then
  57. * increment @rd_idx to move to next entry in trace buffer
  58. */
  59. if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) {
  60. fnic_trace_entries.rd_idx++;
  61. if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries)
  62. fnic_trace_entries.rd_idx = 0;
  63. }
  64. spin_unlock_irqrestore(&fnic_trace_lock, flags);
  65. return (fnic_trace_data_t *)fnic_buf_head;
  66. }
  67. /*
  68. * fnic_get_trace_data - Copy trace buffer to a memory file
  69. * @fnic_dbgfs_t: pointer to debugfs trace buffer
  70. *
  71. * Description:
  72. * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t
  73. * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in
  74. * the log and process the log until the end of the buffer. Then it will gather
  75. * from the beginning of the log and process until the current entry @wr_idx.
  76. *
  77. * Return Value:
  78. * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t
  79. */
  80. int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
  81. {
  82. int rd_idx;
  83. int wr_idx;
  84. int len = 0;
  85. unsigned long flags;
  86. char str[KSYM_SYMBOL_LEN];
  87. struct timespec64 val;
  88. fnic_trace_data_t *tbp;
  89. spin_lock_irqsave(&fnic_trace_lock, flags);
  90. rd_idx = fnic_trace_entries.rd_idx;
  91. wr_idx = fnic_trace_entries.wr_idx;
  92. if (wr_idx < rd_idx) {
  93. while (1) {
  94. /* Start from read index @rd_idx */
  95. tbp = (fnic_trace_data_t *)
  96. fnic_trace_entries.page_offset[rd_idx];
  97. if (!tbp) {
  98. spin_unlock_irqrestore(&fnic_trace_lock, flags);
  99. return 0;
  100. }
  101. /* Convert function pointer to function name */
  102. if (sizeof(unsigned long) < 8) {
  103. sprint_symbol(str, tbp->fnaddr.low);
  104. jiffies_to_timespec64(tbp->timestamp.low, &val);
  105. } else {
  106. sprint_symbol(str, tbp->fnaddr.val);
  107. jiffies_to_timespec64(tbp->timestamp.val, &val);
  108. }
  109. /*
  110. * Dump trace buffer entry to memory file
  111. * and increment read index @rd_idx
  112. */
  113. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  114. (trace_max_pages * PAGE_SIZE * 3) - len,
  115. "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
  116. "%16llx %16llx %16llx\n", (u64)val.tv_sec,
  117. val.tv_nsec, str, tbp->host_no, tbp->tag,
  118. tbp->data[0], tbp->data[1], tbp->data[2],
  119. tbp->data[3], tbp->data[4]);
  120. rd_idx++;
  121. /*
  122. * If rd_idx is reached to maximum trace entries
  123. * then move rd_idx to zero
  124. */
  125. if (rd_idx > (fnic_max_trace_entries-1))
  126. rd_idx = 0;
  127. /*
  128. * Continue dumping trace buffer entries into
  129. * memory file till rd_idx reaches write index
  130. */
  131. if (rd_idx == wr_idx)
  132. break;
  133. }
  134. } else if (wr_idx > rd_idx) {
  135. while (1) {
  136. /* Start from read index @rd_idx */
  137. tbp = (fnic_trace_data_t *)
  138. fnic_trace_entries.page_offset[rd_idx];
  139. if (!tbp) {
  140. spin_unlock_irqrestore(&fnic_trace_lock, flags);
  141. return 0;
  142. }
  143. /* Convert function pointer to function name */
  144. if (sizeof(unsigned long) < 8) {
  145. sprint_symbol(str, tbp->fnaddr.low);
  146. jiffies_to_timespec64(tbp->timestamp.low, &val);
  147. } else {
  148. sprint_symbol(str, tbp->fnaddr.val);
  149. jiffies_to_timespec64(tbp->timestamp.val, &val);
  150. }
  151. /*
  152. * Dump trace buffer entry to memory file
  153. * and increment read index @rd_idx
  154. */
  155. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  156. (trace_max_pages * PAGE_SIZE * 3) - len,
  157. "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
  158. "%16llx %16llx %16llx\n", (u64)val.tv_sec,
  159. val.tv_nsec, str, tbp->host_no, tbp->tag,
  160. tbp->data[0], tbp->data[1], tbp->data[2],
  161. tbp->data[3], tbp->data[4]);
  162. rd_idx++;
  163. /*
  164. * Continue dumping trace buffer entries into
  165. * memory file till rd_idx reaches write index
  166. */
  167. if (rd_idx == wr_idx)
  168. break;
  169. }
  170. }
  171. spin_unlock_irqrestore(&fnic_trace_lock, flags);
  172. return len;
  173. }
  174. /*
  175. * fnic_get_stats_data - Copy fnic stats buffer to a memory file
  176. * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer
  177. *
  178. * Description:
  179. * This routine gathers the fnic stats debugfs data from the fnic_stats struct
  180. * and dumps it to stats_debug_info.
  181. *
  182. * Return Value:
  183. * This routine returns the amount of bytes that were dumped into
  184. * stats_debug_info
  185. */
  186. int fnic_get_stats_data(struct stats_debug_info *debug,
  187. struct fnic_stats *stats)
  188. {
  189. int len = 0;
  190. int buf_size = debug->buf_size;
  191. struct timespec64 val1, val2;
  192. int i = 0;
  193. ktime_get_real_ts64(&val1);
  194. len = scnprintf(debug->debug_buffer + len, buf_size - len,
  195. "------------------------------------------\n"
  196. "\t\tTime\n"
  197. "------------------------------------------\n");
  198. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  199. "Current time : [%lld:%ld]\n"
  200. "Last stats reset time: [%lld:%09ld]\n"
  201. "Last stats read time: [%lld:%ld]\n"
  202. "delta since last reset: [%lld:%ld]\n"
  203. "delta since last read: [%lld:%ld]\n",
  204. (s64)val1.tv_sec, val1.tv_nsec,
  205. (s64)stats->stats_timestamps.last_reset_time.tv_sec,
  206. stats->stats_timestamps.last_reset_time.tv_nsec,
  207. (s64)stats->stats_timestamps.last_read_time.tv_sec,
  208. stats->stats_timestamps.last_read_time.tv_nsec,
  209. (s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
  210. timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
  211. (s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
  212. timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
  213. stats->stats_timestamps.last_read_time = val1;
  214. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  215. "------------------------------------------\n"
  216. "\t\tIO Statistics\n"
  217. "------------------------------------------\n");
  218. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  219. "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n"
  220. "Number of IOs: %lld\nNumber of IO Completions: %lld\n"
  221. "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
  222. "Number of Memory alloc Failures: %lld\n"
  223. "Number of IOREQ Null: %lld\n"
  224. "Number of SCSI cmd pointer Null: %lld\n"
  225. "\nIO completion times: \n"
  226. " < 10 ms : %lld\n"
  227. " 10 ms - 100 ms : %lld\n"
  228. " 100 ms - 500 ms : %lld\n"
  229. " 500 ms - 5 sec: %lld\n"
  230. " 5 sec - 10 sec: %lld\n"
  231. " 10 sec - 30 sec: %lld\n"
  232. " > 30 sec: %lld\n",
  233. (u64)atomic64_read(&stats->io_stats.active_ios),
  234. (u64)atomic64_read(&stats->io_stats.max_active_ios),
  235. (u64)atomic64_read(&stats->io_stats.num_ios),
  236. (u64)atomic64_read(&stats->io_stats.io_completions),
  237. (u64)atomic64_read(&stats->io_stats.io_failures),
  238. (u64)atomic64_read(&stats->io_stats.io_not_found),
  239. (u64)atomic64_read(&stats->io_stats.alloc_failures),
  240. (u64)atomic64_read(&stats->io_stats.ioreq_null),
  241. (u64)atomic64_read(&stats->io_stats.sc_null),
  242. (u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec),
  243. (u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec),
  244. (u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec),
  245. (u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec),
  246. (u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec),
  247. (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
  248. (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
  249. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  250. "------------------------------------------\n"
  251. "\t\tIO Queues and cumulative IOs\n"
  252. "------------------------------------------\n");
  253. for (i = 0; i < FNIC_MQ_MAX_QUEUES; i++) {
  254. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  255. "Q:%d -> %lld\n", i, (u64)atomic64_read(&stats->io_stats.ios[i]));
  256. }
  257. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  258. "\nCurrent Max IO time : %lld\n",
  259. (u64)atomic64_read(&stats->io_stats.current_max_io_time));
  260. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  261. "\n------------------------------------------\n"
  262. "\t\tAbort Statistics\n"
  263. "------------------------------------------\n");
  264. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  265. "Number of Aborts: %lld\n"
  266. "Number of Abort Failures: %lld\n"
  267. "Number of Abort Driver Timeouts: %lld\n"
  268. "Number of Abort FW Timeouts: %lld\n"
  269. "Number of Abort IO NOT Found: %lld\n"
  270. "Abort issued times: \n"
  271. " < 6 sec : %lld\n"
  272. " 6 sec - 20 sec : %lld\n"
  273. " 20 sec - 30 sec : %lld\n"
  274. " 30 sec - 40 sec : %lld\n"
  275. " 40 sec - 50 sec : %lld\n"
  276. " 50 sec - 60 sec : %lld\n"
  277. " > 60 sec: %lld\n",
  278. (u64)atomic64_read(&stats->abts_stats.aborts),
  279. (u64)atomic64_read(&stats->abts_stats.abort_failures),
  280. (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts),
  281. (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts),
  282. (u64)atomic64_read(&stats->abts_stats.abort_io_not_found),
  283. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec),
  284. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec),
  285. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec),
  286. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec),
  287. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec),
  288. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec),
  289. (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec));
  290. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  291. "\n------------------------------------------\n"
  292. "\t\tTerminate Statistics\n"
  293. "------------------------------------------\n");
  294. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  295. "Number of Terminates: %lld\n"
  296. "Maximum Terminates: %lld\n"
  297. "Number of Terminate Driver Timeouts: %lld\n"
  298. "Number of Terminate FW Timeouts: %lld\n"
  299. "Number of Terminate IO NOT Found: %lld\n"
  300. "Number of Terminate Failures: %lld\n",
  301. (u64)atomic64_read(&stats->term_stats.terminates),
  302. (u64)atomic64_read(&stats->term_stats.max_terminates),
  303. (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts),
  304. (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts),
  305. (u64)atomic64_read(&stats->term_stats.terminate_io_not_found),
  306. (u64)atomic64_read(&stats->term_stats.terminate_failures));
  307. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  308. "\n------------------------------------------\n"
  309. "\t\tReset Statistics\n"
  310. "------------------------------------------\n");
  311. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  312. "Number of Device Resets: %lld\n"
  313. "Number of Device Reset Failures: %lld\n"
  314. "Number of Device Reset Aborts: %lld\n"
  315. "Number of Device Reset Timeouts: %lld\n"
  316. "Number of Device Reset Terminates: %lld\n"
  317. "Number of FW Resets: %lld\n"
  318. "Number of FW Reset Completions: %lld\n"
  319. "Number of FW Reset Failures: %lld\n"
  320. "Number of Fnic Reset: %lld\n"
  321. "Number of Fnic Reset Completions: %lld\n"
  322. "Number of Fnic Reset Failures: %lld\n",
  323. (u64)atomic64_read(&stats->reset_stats.device_resets),
  324. (u64)atomic64_read(&stats->reset_stats.device_reset_failures),
  325. (u64)atomic64_read(&stats->reset_stats.device_reset_aborts),
  326. (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts),
  327. (u64)atomic64_read(
  328. &stats->reset_stats.device_reset_terminates),
  329. (u64)atomic64_read(&stats->reset_stats.fw_resets),
  330. (u64)atomic64_read(&stats->reset_stats.fw_reset_completions),
  331. (u64)atomic64_read(&stats->reset_stats.fw_reset_failures),
  332. (u64)atomic64_read(&stats->reset_stats.fnic_resets),
  333. (u64)atomic64_read(
  334. &stats->reset_stats.fnic_reset_completions),
  335. (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures));
  336. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  337. "\n------------------------------------------\n"
  338. "\t\tFirmware Statistics\n"
  339. "------------------------------------------\n");
  340. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  341. "Number of Active FW Requests %lld\n"
  342. "Maximum FW Requests: %lld\n"
  343. "Number of FW out of resources: %lld\n"
  344. "Number of FW IO errors: %lld\n",
  345. (u64)atomic64_read(&stats->fw_stats.active_fw_reqs),
  346. (u64)atomic64_read(&stats->fw_stats.max_fw_reqs),
  347. (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources),
  348. (u64)atomic64_read(&stats->fw_stats.io_fw_errs));
  349. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  350. "\n------------------------------------------\n"
  351. "\t\tVlan Discovery Statistics\n"
  352. "------------------------------------------\n");
  353. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  354. "Number of Vlan Discovery Requests Sent %lld\n"
  355. "Vlan Response Received with no FCF VLAN ID: %lld\n"
  356. "No solicitations recvd after vlan set, expiry count: %lld\n"
  357. "Flogi rejects count: %lld\n",
  358. (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs),
  359. (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID),
  360. (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count),
  361. (u64)atomic64_read(&stats->vlan_stats.flogi_rejects));
  362. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  363. "\n------------------------------------------\n"
  364. "\t\tOther Important Statistics\n"
  365. "------------------------------------------\n");
  366. jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1);
  367. jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
  368. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  369. "Last ISR time: %llu (%8llu.%09lu)\n"
  370. "Last ACK time: %llu (%8llu.%09lu)\n"
  371. "Max ISR jiffies: %llu\n"
  372. "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
  373. "Corr. work done: %llu\n"
  374. "Number of ISRs: %lld\n"
  375. "Maximum CQ Entries: %lld\n"
  376. "Number of ACK index out of range: %lld\n"
  377. "Number of data count mismatch: %lld\n"
  378. "Number of FCPIO Timeouts: %lld\n"
  379. "Number of FCPIO Aborted: %lld\n"
  380. "Number of SGL Invalid: %lld\n"
  381. "Number of Copy WQ Alloc Failures for ABTs: %lld\n"
  382. "Number of Copy WQ Alloc Failures for Device Reset: %lld\n"
  383. "Number of Copy WQ Alloc Failures for IOs: %lld\n"
  384. "Number of no icmnd itmf Completions: %lld\n"
  385. "Number of Check Conditions encountered: %lld\n"
  386. "Number of QUEUE Fulls: %lld\n"
  387. "Number of rport not ready: %lld\n"
  388. "Number of receive frame errors: %lld\n",
  389. (u64)stats->misc_stats.last_isr_time,
  390. (s64)val1.tv_sec, val1.tv_nsec,
  391. (u64)stats->misc_stats.last_ack_time,
  392. (s64)val2.tv_sec, val2.tv_nsec,
  393. (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
  394. (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
  395. (u64)atomic64_read(&stats->misc_stats.corr_work_done),
  396. (u64)atomic64_read(&stats->misc_stats.isr_count),
  397. (u64)atomic64_read(&stats->misc_stats.max_cq_entries),
  398. (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range),
  399. (u64)atomic64_read(&stats->misc_stats.data_count_mismatch),
  400. (u64)atomic64_read(&stats->misc_stats.fcpio_timeout),
  401. (u64)atomic64_read(&stats->misc_stats.fcpio_aborted),
  402. (u64)atomic64_read(&stats->misc_stats.sgl_invalid),
  403. (u64)atomic64_read(
  404. &stats->misc_stats.abts_cpwq_alloc_failures),
  405. (u64)atomic64_read(
  406. &stats->misc_stats.devrst_cpwq_alloc_failures),
  407. (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures),
  408. (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls),
  409. (u64)atomic64_read(&stats->misc_stats.check_condition),
  410. (u64)atomic64_read(&stats->misc_stats.queue_fulls),
  411. (u64)atomic64_read(&stats->misc_stats.rport_not_ready),
  412. (u64)atomic64_read(&stats->misc_stats.frame_errors));
  413. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  414. "Firmware reported port speed: %llu\n",
  415. (u64)atomic64_read(
  416. &stats->misc_stats.current_port_speed));
  417. return len;
  418. }
  419. /*
  420. * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
  421. *
  422. * Description:
  423. * Initialize trace buffer data structure by allocating required memory and
  424. * setting page_offset information for every trace entry by adding trace entry
  425. * length to previous page_offset value.
  426. */
  427. int fnic_trace_buf_init(void)
  428. {
  429. unsigned long fnic_buf_head;
  430. int i;
  431. int err = 0;
  432. trace_max_pages = fnic_trace_max_pages;
  433. fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
  434. FNIC_ENTRY_SIZE_BYTES;
  435. fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE);
  436. if (!fnic_trace_buf_p) {
  437. printk(KERN_ERR PFX "Failed to allocate memory "
  438. "for fnic_trace_buf_p\n");
  439. err = -ENOMEM;
  440. goto err_fnic_trace_buf_init;
  441. }
  442. fnic_trace_entries.page_offset =
  443. vmalloc(array_size(fnic_max_trace_entries,
  444. sizeof(unsigned long)));
  445. if (!fnic_trace_entries.page_offset) {
  446. printk(KERN_ERR PFX "Failed to allocate memory for"
  447. " page_offset\n");
  448. if (fnic_trace_buf_p) {
  449. vfree((void *)fnic_trace_buf_p);
  450. fnic_trace_buf_p = 0;
  451. }
  452. err = -ENOMEM;
  453. goto err_fnic_trace_buf_init;
  454. }
  455. memset((void *)fnic_trace_entries.page_offset, 0,
  456. (fnic_max_trace_entries * sizeof(unsigned long)));
  457. fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
  458. fnic_buf_head = fnic_trace_buf_p;
  459. /*
  460. * Set page_offset field of fnic_trace_entries struct by
  461. * calculating memory location for every trace entry using
  462. * length of each trace entry
  463. */
  464. for (i = 0; i < fnic_max_trace_entries; i++) {
  465. fnic_trace_entries.page_offset[i] = fnic_buf_head;
  466. fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
  467. }
  468. fnic_trace_debugfs_init();
  469. pr_info("fnic: Successfully Initialized Trace Buffer\n");
  470. return err;
  471. err_fnic_trace_buf_init:
  472. return err;
  473. }
  474. /*
  475. * fnic_trace_free - Free memory of fnic trace data structures.
  476. */
  477. void fnic_trace_free(void)
  478. {
  479. fnic_tracing_enabled = 0;
  480. fnic_trace_debugfs_terminate();
  481. if (fnic_trace_entries.page_offset) {
  482. vfree((void *)fnic_trace_entries.page_offset);
  483. fnic_trace_entries.page_offset = NULL;
  484. }
  485. if (fnic_trace_buf_p) {
  486. vfree((void *)fnic_trace_buf_p);
  487. fnic_trace_buf_p = 0;
  488. }
  489. printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
  490. }
  491. /*
  492. * fnic_fc_ctlr_trace_buf_init -
  493. * Initialize trace buffer to log fnic control frames
  494. * Description:
  495. * Initialize trace buffer data structure by allocating
  496. * required memory for trace data as well as for Indexes.
  497. * Frame size is 256 bytes and
  498. * memory is allocated for 1024 entries of 256 bytes.
  499. * Page_offset(Index) is set to the address of trace entry
  500. * and page_offset is initialized by adding frame size
  501. * to the previous page_offset entry.
  502. */
  503. int fnic_fc_trace_init(void)
  504. {
  505. unsigned long fc_trace_buf_head;
  506. int err = 0;
  507. int i;
  508. fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/
  509. FC_TRC_SIZE_BYTES;
  510. fnic_fc_ctlr_trace_buf_p =
  511. (unsigned long)vmalloc(array_size(PAGE_SIZE,
  512. fnic_fc_trace_max_pages));
  513. if (!fnic_fc_ctlr_trace_buf_p) {
  514. pr_err("fnic: Failed to allocate memory for "
  515. "FC Control Trace Buf\n");
  516. err = -ENOMEM;
  517. goto err_fnic_fc_ctlr_trace_buf_init;
  518. }
  519. memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
  520. fnic_fc_trace_max_pages * PAGE_SIZE);
  521. /* Allocate memory for page offset */
  522. fc_trace_entries.page_offset =
  523. vmalloc(array_size(fc_trace_max_entries,
  524. sizeof(unsigned long)));
  525. if (!fc_trace_entries.page_offset) {
  526. pr_err("fnic:Failed to allocate memory for page_offset\n");
  527. if (fnic_fc_ctlr_trace_buf_p) {
  528. pr_err("fnic: Freeing FC Control Trace Buf\n");
  529. vfree((void *)fnic_fc_ctlr_trace_buf_p);
  530. fnic_fc_ctlr_trace_buf_p = 0;
  531. }
  532. err = -ENOMEM;
  533. goto err_fnic_fc_ctlr_trace_buf_init;
  534. }
  535. memset((void *)fc_trace_entries.page_offset, 0,
  536. (fc_trace_max_entries * sizeof(unsigned long)));
  537. fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
  538. fc_trace_buf_head = fnic_fc_ctlr_trace_buf_p;
  539. /*
  540. * Set up fc_trace_entries.page_offset field with memory location
  541. * for every trace entry
  542. */
  543. for (i = 0; i < fc_trace_max_entries; i++) {
  544. fc_trace_entries.page_offset[i] = fc_trace_buf_head;
  545. fc_trace_buf_head += FC_TRC_SIZE_BYTES;
  546. }
  547. fnic_fc_trace_debugfs_init();
  548. pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n");
  549. return err;
  550. err_fnic_fc_ctlr_trace_buf_init:
  551. return err;
  552. }
  553. /*
  554. * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures.
  555. */
  556. void fnic_fc_trace_free(void)
  557. {
  558. fnic_fc_tracing_enabled = 0;
  559. fnic_fc_trace_debugfs_terminate();
  560. if (fc_trace_entries.page_offset) {
  561. vfree((void *)fc_trace_entries.page_offset);
  562. fc_trace_entries.page_offset = NULL;
  563. }
  564. if (fnic_fc_ctlr_trace_buf_p) {
  565. vfree((void *)fnic_fc_ctlr_trace_buf_p);
  566. fnic_fc_ctlr_trace_buf_p = 0;
  567. }
  568. pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n");
  569. }
  570. /*
  571. * fnic_fc_ctlr_set_trace_data:
  572. * Maintain rd & wr idx accordingly and set data
  573. * Passed parameters:
  574. * host_no: host number associated with fnic
  575. * frame_type: send_frame, rece_frame or link event
  576. * fc_frame: pointer to fc_frame
  577. * frame_len: Length of the fc_frame
  578. * Description:
  579. * This routine will get next available wr_idx and
  580. * copy all passed trace data to the buffer pointed by wr_idx
  581. * and increment wr_idx. It will also make sure that we dont
  582. * overwrite the entry which we are reading and also
  583. * wrap around if we reach the maximum entries.
  584. * Returned Value:
  585. * It will return 0 for success or -1 for failure
  586. */
  587. int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
  588. char *frame, u32 fc_trc_frame_len)
  589. {
  590. unsigned long flags;
  591. struct fc_trace_hdr *fc_buf;
  592. unsigned long eth_fcoe_hdr_len;
  593. char *fc_trace;
  594. if (fnic_fc_tracing_enabled == 0)
  595. return 0;
  596. spin_lock_irqsave(&fnic_fc_trace_lock, flags);
  597. if (fnic_fc_trace_cleared == 1) {
  598. fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
  599. pr_info("fnic: Resetting the read idx\n");
  600. memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
  601. fnic_fc_trace_max_pages * PAGE_SIZE);
  602. fnic_fc_trace_cleared = 0;
  603. }
  604. fc_buf = (struct fc_trace_hdr *)
  605. fc_trace_entries.page_offset[fc_trace_entries.wr_idx];
  606. fc_trace_entries.wr_idx++;
  607. if (fc_trace_entries.wr_idx >= fc_trace_max_entries)
  608. fc_trace_entries.wr_idx = 0;
  609. if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
  610. fc_trace_entries.rd_idx++;
  611. if (fc_trace_entries.rd_idx >= fc_trace_max_entries)
  612. fc_trace_entries.rd_idx = 0;
  613. }
  614. ktime_get_real_ts64(&fc_buf->time_stamp);
  615. fc_buf->host_no = host_no;
  616. fc_buf->frame_type = frame_type;
  617. fc_trace = (char *)FC_TRACE_ADDRESS(fc_buf);
  618. /* During the receive path, we do not have eth hdr as well as fcoe hdr
  619. * at trace entry point so we will stuff 0xff just to make it generic.
  620. */
  621. if (frame_type == FNIC_FC_RECV) {
  622. eth_fcoe_hdr_len = sizeof(struct ethhdr) +
  623. sizeof(struct fcoe_hdr);
  624. memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
  625. /* Copy the rest of data frame */
  626. memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
  627. min_t(u8, fc_trc_frame_len,
  628. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
  629. - eth_fcoe_hdr_len)));
  630. } else {
  631. memcpy((char *)fc_trace, (void *)frame,
  632. min_t(u8, fc_trc_frame_len,
  633. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
  634. }
  635. /* Store the actual received length */
  636. fc_buf->frame_len = fc_trc_frame_len;
  637. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  638. return 0;
  639. }
  640. /*
  641. * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file
  642. * Passed parameter:
  643. * @fnic_dbgfs_t: pointer to debugfs trace buffer
  644. * rdata_flag: 1 => Unformatted file
  645. * 0 => formatted file
  646. * Description:
  647. * This routine will copy the trace data to memory file with
  648. * proper formatting and also copy to another memory
  649. * file without formatting for further processing.
  650. * Return Value:
  651. * Number of bytes that were dumped into fnic_dbgfs_t
  652. */
  653. int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag)
  654. {
  655. int rd_idx, wr_idx;
  656. unsigned long flags;
  657. int len = 0, j;
  658. struct fc_trace_hdr *tdata;
  659. char *fc_trace;
  660. spin_lock_irqsave(&fnic_fc_trace_lock, flags);
  661. if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
  662. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  663. pr_info("fnic: Buffer is empty\n");
  664. return 0;
  665. }
  666. rd_idx = fc_trace_entries.rd_idx;
  667. wr_idx = fc_trace_entries.wr_idx;
  668. if (rdata_flag == 0) {
  669. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  670. (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
  671. "Time Stamp (UTC)\t\t"
  672. "Host No: F Type: len: FCoE_FRAME:\n");
  673. }
  674. while (rd_idx != wr_idx) {
  675. tdata = (struct fc_trace_hdr *)
  676. fc_trace_entries.page_offset[rd_idx];
  677. if (!tdata) {
  678. pr_info("fnic: Rd data is NULL\n");
  679. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  680. return 0;
  681. }
  682. if (rdata_flag == 0) {
  683. copy_and_format_trace_data(tdata,
  684. fnic_dbgfs_prt, &len, rdata_flag);
  685. } else {
  686. fc_trace = (char *)tdata;
  687. for (j = 0; j < FC_TRC_SIZE_BYTES; j++) {
  688. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  689. (fnic_fc_trace_max_pages * PAGE_SIZE * 3)
  690. - len, "%02x", fc_trace[j] & 0xff);
  691. } /* for loop */
  692. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  693. (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
  694. "\n");
  695. }
  696. rd_idx++;
  697. if (rd_idx > (fc_trace_max_entries - 1))
  698. rd_idx = 0;
  699. }
  700. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  701. return len;
  702. }
  703. /*
  704. * copy_and_format_trace_data: Copy formatted data to char * buffer
  705. * Passed Parameter:
  706. * @fc_trace_hdr_t: pointer to trace data
  707. * @fnic_dbgfs_t: pointer to debugfs trace buffer
  708. * @orig_len: pointer to len
  709. * rdata_flag: 0 => Formatted file, 1 => Unformatted file
  710. * Description:
  711. * This routine will format and copy the passed trace data
  712. * for formatted file or unformatted file accordingly.
  713. */
  714. void copy_and_format_trace_data(struct fc_trace_hdr *tdata,
  715. fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len,
  716. u8 rdata_flag)
  717. {
  718. int j, i = 1, len;
  719. int ethhdr_len = sizeof(struct ethhdr) - 1;
  720. int fcoehdr_len = sizeof(struct fcoe_hdr);
  721. int fchdr_len = sizeof(struct fc_frame_header);
  722. int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3;
  723. char *fc_trace;
  724. tdata->frame_type = tdata->frame_type & 0x7F;
  725. len = *orig_len;
  726. len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len,
  727. "%ptTs.%09lu ns%8x %c%8x\t",
  728. &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec,
  729. tdata->host_no, tdata->frame_type, tdata->frame_len);
  730. fc_trace = (char *)FC_TRACE_ADDRESS(tdata);
  731. for (j = 0; j < min_t(u8, tdata->frame_len,
  732. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) {
  733. if (tdata->frame_type == FNIC_FC_LE) {
  734. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  735. max_size - len, "%c", fc_trace[j]);
  736. } else {
  737. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  738. max_size - len, "%02x", fc_trace[j] & 0xff);
  739. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  740. max_size - len, " ");
  741. if (j == ethhdr_len ||
  742. j == ethhdr_len + fcoehdr_len ||
  743. j == ethhdr_len + fcoehdr_len + fchdr_len ||
  744. (i > 3 && j%fchdr_len == 0)) {
  745. len += scnprintf(fnic_dbgfs_prt->buffer
  746. + len, max_size - len,
  747. "\n\t\t\t\t\t\t\t\t");
  748. i++;
  749. }
  750. } /* end of else*/
  751. } /* End of for loop*/
  752. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  753. max_size - len, "\n");
  754. *orig_len = len;
  755. }