fnic_trace.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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. ktime_get_real_ts64(&val1);
  193. len = scnprintf(debug->debug_buffer + len, buf_size - len,
  194. "------------------------------------------\n"
  195. "\t\tTime\n"
  196. "------------------------------------------\n");
  197. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  198. "Current time : [%lld:%ld]\n"
  199. "Last stats reset time: [%lld:%09ld]\n"
  200. "Last stats read time: [%lld:%ld]\n"
  201. "delta since last reset: [%lld:%ld]\n"
  202. "delta since last read: [%lld:%ld]\n",
  203. (s64)val1.tv_sec, val1.tv_nsec,
  204. (s64)stats->stats_timestamps.last_reset_time.tv_sec,
  205. stats->stats_timestamps.last_reset_time.tv_nsec,
  206. (s64)stats->stats_timestamps.last_read_time.tv_sec,
  207. stats->stats_timestamps.last_read_time.tv_nsec,
  208. (s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
  209. timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
  210. (s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
  211. timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
  212. stats->stats_timestamps.last_read_time = val1;
  213. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  214. "------------------------------------------\n"
  215. "\t\tIO Statistics\n"
  216. "------------------------------------------\n");
  217. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  218. "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n"
  219. "Number of IOs: %lld\nNumber of IO Completions: %lld\n"
  220. "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
  221. "Number of Memory alloc Failures: %lld\n"
  222. "Number of IOREQ Null: %lld\n"
  223. "Number of SCSI cmd pointer Null: %lld\n"
  224. "\nIO completion times: \n"
  225. " < 10 ms : %lld\n"
  226. " 10 ms - 100 ms : %lld\n"
  227. " 100 ms - 500 ms : %lld\n"
  228. " 500 ms - 5 sec: %lld\n"
  229. " 5 sec - 10 sec: %lld\n"
  230. " 10 sec - 30 sec: %lld\n"
  231. " > 30 sec: %lld\n",
  232. (u64)atomic64_read(&stats->io_stats.active_ios),
  233. (u64)atomic64_read(&stats->io_stats.max_active_ios),
  234. (u64)atomic64_read(&stats->io_stats.num_ios),
  235. (u64)atomic64_read(&stats->io_stats.io_completions),
  236. (u64)atomic64_read(&stats->io_stats.io_failures),
  237. (u64)atomic64_read(&stats->io_stats.io_not_found),
  238. (u64)atomic64_read(&stats->io_stats.alloc_failures),
  239. (u64)atomic64_read(&stats->io_stats.ioreq_null),
  240. (u64)atomic64_read(&stats->io_stats.sc_null),
  241. (u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec),
  242. (u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec),
  243. (u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec),
  244. (u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec),
  245. (u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec),
  246. (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
  247. (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
  248. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  249. "\nCurrent Max IO time : %lld\n",
  250. (u64)atomic64_read(&stats->io_stats.current_max_io_time));
  251. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  252. "\n------------------------------------------\n"
  253. "\t\tAbort Statistics\n"
  254. "------------------------------------------\n");
  255. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  256. "Number of Aborts: %lld\n"
  257. "Number of Abort Failures: %lld\n"
  258. "Number of Abort Driver Timeouts: %lld\n"
  259. "Number of Abort FW Timeouts: %lld\n"
  260. "Number of Abort IO NOT Found: %lld\n"
  261. "Abort issued times: \n"
  262. " < 6 sec : %lld\n"
  263. " 6 sec - 20 sec : %lld\n"
  264. " 20 sec - 30 sec : %lld\n"
  265. " 30 sec - 40 sec : %lld\n"
  266. " 40 sec - 50 sec : %lld\n"
  267. " 50 sec - 60 sec : %lld\n"
  268. " > 60 sec: %lld\n",
  269. (u64)atomic64_read(&stats->abts_stats.aborts),
  270. (u64)atomic64_read(&stats->abts_stats.abort_failures),
  271. (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts),
  272. (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts),
  273. (u64)atomic64_read(&stats->abts_stats.abort_io_not_found),
  274. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec),
  275. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec),
  276. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec),
  277. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec),
  278. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec),
  279. (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec),
  280. (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec));
  281. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  282. "\n------------------------------------------\n"
  283. "\t\tTerminate Statistics\n"
  284. "------------------------------------------\n");
  285. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  286. "Number of Terminates: %lld\n"
  287. "Maximum Terminates: %lld\n"
  288. "Number of Terminate Driver Timeouts: %lld\n"
  289. "Number of Terminate FW Timeouts: %lld\n"
  290. "Number of Terminate IO NOT Found: %lld\n"
  291. "Number of Terminate Failures: %lld\n",
  292. (u64)atomic64_read(&stats->term_stats.terminates),
  293. (u64)atomic64_read(&stats->term_stats.max_terminates),
  294. (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts),
  295. (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts),
  296. (u64)atomic64_read(&stats->term_stats.terminate_io_not_found),
  297. (u64)atomic64_read(&stats->term_stats.terminate_failures));
  298. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  299. "\n------------------------------------------\n"
  300. "\t\tReset Statistics\n"
  301. "------------------------------------------\n");
  302. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  303. "Number of Device Resets: %lld\n"
  304. "Number of Device Reset Failures: %lld\n"
  305. "Number of Device Reset Aborts: %lld\n"
  306. "Number of Device Reset Timeouts: %lld\n"
  307. "Number of Device Reset Terminates: %lld\n"
  308. "Number of FW Resets: %lld\n"
  309. "Number of FW Reset Completions: %lld\n"
  310. "Number of FW Reset Failures: %lld\n"
  311. "Number of Fnic Reset: %lld\n"
  312. "Number of Fnic Reset Completions: %lld\n"
  313. "Number of Fnic Reset Failures: %lld\n",
  314. (u64)atomic64_read(&stats->reset_stats.device_resets),
  315. (u64)atomic64_read(&stats->reset_stats.device_reset_failures),
  316. (u64)atomic64_read(&stats->reset_stats.device_reset_aborts),
  317. (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts),
  318. (u64)atomic64_read(
  319. &stats->reset_stats.device_reset_terminates),
  320. (u64)atomic64_read(&stats->reset_stats.fw_resets),
  321. (u64)atomic64_read(&stats->reset_stats.fw_reset_completions),
  322. (u64)atomic64_read(&stats->reset_stats.fw_reset_failures),
  323. (u64)atomic64_read(&stats->reset_stats.fnic_resets),
  324. (u64)atomic64_read(
  325. &stats->reset_stats.fnic_reset_completions),
  326. (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures));
  327. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  328. "\n------------------------------------------\n"
  329. "\t\tFirmware Statistics\n"
  330. "------------------------------------------\n");
  331. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  332. "Number of Active FW Requests %lld\n"
  333. "Maximum FW Requests: %lld\n"
  334. "Number of FW out of resources: %lld\n"
  335. "Number of FW IO errors: %lld\n",
  336. (u64)atomic64_read(&stats->fw_stats.active_fw_reqs),
  337. (u64)atomic64_read(&stats->fw_stats.max_fw_reqs),
  338. (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources),
  339. (u64)atomic64_read(&stats->fw_stats.io_fw_errs));
  340. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  341. "\n------------------------------------------\n"
  342. "\t\tVlan Discovery Statistics\n"
  343. "------------------------------------------\n");
  344. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  345. "Number of Vlan Discovery Requests Sent %lld\n"
  346. "Vlan Response Received with no FCF VLAN ID: %lld\n"
  347. "No solicitations recvd after vlan set, expiry count: %lld\n"
  348. "Flogi rejects count: %lld\n",
  349. (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs),
  350. (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID),
  351. (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count),
  352. (u64)atomic64_read(&stats->vlan_stats.flogi_rejects));
  353. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  354. "\n------------------------------------------\n"
  355. "\t\tOther Important Statistics\n"
  356. "------------------------------------------\n");
  357. jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1);
  358. jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
  359. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  360. "Last ISR time: %llu (%8llu.%09lu)\n"
  361. "Last ACK time: %llu (%8llu.%09lu)\n"
  362. "Max ISR jiffies: %llu\n"
  363. "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
  364. "Corr. work done: %llu\n"
  365. "Number of ISRs: %lld\n"
  366. "Maximum CQ Entries: %lld\n"
  367. "Number of ACK index out of range: %lld\n"
  368. "Number of data count mismatch: %lld\n"
  369. "Number of FCPIO Timeouts: %lld\n"
  370. "Number of FCPIO Aborted: %lld\n"
  371. "Number of SGL Invalid: %lld\n"
  372. "Number of Copy WQ Alloc Failures for ABTs: %lld\n"
  373. "Number of Copy WQ Alloc Failures for Device Reset: %lld\n"
  374. "Number of Copy WQ Alloc Failures for IOs: %lld\n"
  375. "Number of no icmnd itmf Completions: %lld\n"
  376. "Number of Check Conditions encountered: %lld\n"
  377. "Number of QUEUE Fulls: %lld\n"
  378. "Number of rport not ready: %lld\n"
  379. "Number of receive frame errors: %lld\n",
  380. (u64)stats->misc_stats.last_isr_time,
  381. (s64)val1.tv_sec, val1.tv_nsec,
  382. (u64)stats->misc_stats.last_ack_time,
  383. (s64)val2.tv_sec, val2.tv_nsec,
  384. (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
  385. (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
  386. (u64)atomic64_read(&stats->misc_stats.corr_work_done),
  387. (u64)atomic64_read(&stats->misc_stats.isr_count),
  388. (u64)atomic64_read(&stats->misc_stats.max_cq_entries),
  389. (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range),
  390. (u64)atomic64_read(&stats->misc_stats.data_count_mismatch),
  391. (u64)atomic64_read(&stats->misc_stats.fcpio_timeout),
  392. (u64)atomic64_read(&stats->misc_stats.fcpio_aborted),
  393. (u64)atomic64_read(&stats->misc_stats.sgl_invalid),
  394. (u64)atomic64_read(
  395. &stats->misc_stats.abts_cpwq_alloc_failures),
  396. (u64)atomic64_read(
  397. &stats->misc_stats.devrst_cpwq_alloc_failures),
  398. (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures),
  399. (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls),
  400. (u64)atomic64_read(&stats->misc_stats.check_condition),
  401. (u64)atomic64_read(&stats->misc_stats.queue_fulls),
  402. (u64)atomic64_read(&stats->misc_stats.rport_not_ready),
  403. (u64)atomic64_read(&stats->misc_stats.frame_errors));
  404. len += scnprintf(debug->debug_buffer + len, buf_size - len,
  405. "Firmware reported port speed: %llu\n",
  406. (u64)atomic64_read(
  407. &stats->misc_stats.current_port_speed));
  408. return len;
  409. }
  410. /*
  411. * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
  412. *
  413. * Description:
  414. * Initialize trace buffer data structure by allocating required memory and
  415. * setting page_offset information for every trace entry by adding trace entry
  416. * length to previous page_offset value.
  417. */
  418. int fnic_trace_buf_init(void)
  419. {
  420. unsigned long fnic_buf_head;
  421. int i;
  422. int err = 0;
  423. trace_max_pages = fnic_trace_max_pages;
  424. fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
  425. FNIC_ENTRY_SIZE_BYTES;
  426. fnic_trace_buf_p = (unsigned long)vzalloc(trace_max_pages * PAGE_SIZE);
  427. if (!fnic_trace_buf_p) {
  428. printk(KERN_ERR PFX "Failed to allocate memory "
  429. "for fnic_trace_buf_p\n");
  430. err = -ENOMEM;
  431. goto err_fnic_trace_buf_init;
  432. }
  433. fnic_trace_entries.page_offset =
  434. vmalloc(array_size(fnic_max_trace_entries,
  435. sizeof(unsigned long)));
  436. if (!fnic_trace_entries.page_offset) {
  437. printk(KERN_ERR PFX "Failed to allocate memory for"
  438. " page_offset\n");
  439. if (fnic_trace_buf_p) {
  440. vfree((void *)fnic_trace_buf_p);
  441. fnic_trace_buf_p = 0;
  442. }
  443. err = -ENOMEM;
  444. goto err_fnic_trace_buf_init;
  445. }
  446. memset((void *)fnic_trace_entries.page_offset, 0,
  447. (fnic_max_trace_entries * sizeof(unsigned long)));
  448. fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
  449. fnic_buf_head = fnic_trace_buf_p;
  450. /*
  451. * Set page_offset field of fnic_trace_entries struct by
  452. * calculating memory location for every trace entry using
  453. * length of each trace entry
  454. */
  455. for (i = 0; i < fnic_max_trace_entries; i++) {
  456. fnic_trace_entries.page_offset[i] = fnic_buf_head;
  457. fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
  458. }
  459. fnic_trace_debugfs_init();
  460. pr_info("fnic: Successfully Initialized Trace Buffer\n");
  461. return err;
  462. err_fnic_trace_buf_init:
  463. return err;
  464. }
  465. /*
  466. * fnic_trace_free - Free memory of fnic trace data structures.
  467. */
  468. void fnic_trace_free(void)
  469. {
  470. fnic_tracing_enabled = 0;
  471. fnic_trace_debugfs_terminate();
  472. if (fnic_trace_entries.page_offset) {
  473. vfree((void *)fnic_trace_entries.page_offset);
  474. fnic_trace_entries.page_offset = NULL;
  475. }
  476. if (fnic_trace_buf_p) {
  477. vfree((void *)fnic_trace_buf_p);
  478. fnic_trace_buf_p = 0;
  479. }
  480. printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
  481. }
  482. /*
  483. * fnic_fc_ctlr_trace_buf_init -
  484. * Initialize trace buffer to log fnic control frames
  485. * Description:
  486. * Initialize trace buffer data structure by allocating
  487. * required memory for trace data as well as for Indexes.
  488. * Frame size is 256 bytes and
  489. * memory is allocated for 1024 entries of 256 bytes.
  490. * Page_offset(Index) is set to the address of trace entry
  491. * and page_offset is initialized by adding frame size
  492. * to the previous page_offset entry.
  493. */
  494. int fnic_fc_trace_init(void)
  495. {
  496. unsigned long fc_trace_buf_head;
  497. int err = 0;
  498. int i;
  499. fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/
  500. FC_TRC_SIZE_BYTES;
  501. fnic_fc_ctlr_trace_buf_p =
  502. (unsigned long)vmalloc(array_size(PAGE_SIZE,
  503. fnic_fc_trace_max_pages));
  504. if (!fnic_fc_ctlr_trace_buf_p) {
  505. pr_err("fnic: Failed to allocate memory for "
  506. "FC Control Trace Buf\n");
  507. err = -ENOMEM;
  508. goto err_fnic_fc_ctlr_trace_buf_init;
  509. }
  510. memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
  511. fnic_fc_trace_max_pages * PAGE_SIZE);
  512. /* Allocate memory for page offset */
  513. fc_trace_entries.page_offset =
  514. vmalloc(array_size(fc_trace_max_entries,
  515. sizeof(unsigned long)));
  516. if (!fc_trace_entries.page_offset) {
  517. pr_err("fnic:Failed to allocate memory for page_offset\n");
  518. if (fnic_fc_ctlr_trace_buf_p) {
  519. pr_err("fnic: Freeing FC Control Trace Buf\n");
  520. vfree((void *)fnic_fc_ctlr_trace_buf_p);
  521. fnic_fc_ctlr_trace_buf_p = 0;
  522. }
  523. err = -ENOMEM;
  524. goto err_fnic_fc_ctlr_trace_buf_init;
  525. }
  526. memset((void *)fc_trace_entries.page_offset, 0,
  527. (fc_trace_max_entries * sizeof(unsigned long)));
  528. fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
  529. fc_trace_buf_head = fnic_fc_ctlr_trace_buf_p;
  530. /*
  531. * Set up fc_trace_entries.page_offset field with memory location
  532. * for every trace entry
  533. */
  534. for (i = 0; i < fc_trace_max_entries; i++) {
  535. fc_trace_entries.page_offset[i] = fc_trace_buf_head;
  536. fc_trace_buf_head += FC_TRC_SIZE_BYTES;
  537. }
  538. fnic_fc_trace_debugfs_init();
  539. pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n");
  540. return err;
  541. err_fnic_fc_ctlr_trace_buf_init:
  542. return err;
  543. }
  544. /*
  545. * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures.
  546. */
  547. void fnic_fc_trace_free(void)
  548. {
  549. fnic_fc_tracing_enabled = 0;
  550. fnic_fc_trace_debugfs_terminate();
  551. if (fc_trace_entries.page_offset) {
  552. vfree((void *)fc_trace_entries.page_offset);
  553. fc_trace_entries.page_offset = NULL;
  554. }
  555. if (fnic_fc_ctlr_trace_buf_p) {
  556. vfree((void *)fnic_fc_ctlr_trace_buf_p);
  557. fnic_fc_ctlr_trace_buf_p = 0;
  558. }
  559. pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n");
  560. }
  561. /*
  562. * fnic_fc_ctlr_set_trace_data:
  563. * Maintain rd & wr idx accordingly and set data
  564. * Passed parameters:
  565. * host_no: host number associated with fnic
  566. * frame_type: send_frame, rece_frame or link event
  567. * fc_frame: pointer to fc_frame
  568. * frame_len: Length of the fc_frame
  569. * Description:
  570. * This routine will get next available wr_idx and
  571. * copy all passed trace data to the buffer pointed by wr_idx
  572. * and increment wr_idx. It will also make sure that we dont
  573. * overwrite the entry which we are reading and also
  574. * wrap around if we reach the maximum entries.
  575. * Returned Value:
  576. * It will return 0 for success or -1 for failure
  577. */
  578. int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
  579. char *frame, u32 fc_trc_frame_len)
  580. {
  581. unsigned long flags;
  582. struct fc_trace_hdr *fc_buf;
  583. unsigned long eth_fcoe_hdr_len;
  584. char *fc_trace;
  585. if (fnic_fc_tracing_enabled == 0)
  586. return 0;
  587. spin_lock_irqsave(&fnic_fc_trace_lock, flags);
  588. if (fnic_fc_trace_cleared == 1) {
  589. fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
  590. pr_info("fnic: Resetting the read idx\n");
  591. memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
  592. fnic_fc_trace_max_pages * PAGE_SIZE);
  593. fnic_fc_trace_cleared = 0;
  594. }
  595. fc_buf = (struct fc_trace_hdr *)
  596. fc_trace_entries.page_offset[fc_trace_entries.wr_idx];
  597. fc_trace_entries.wr_idx++;
  598. if (fc_trace_entries.wr_idx >= fc_trace_max_entries)
  599. fc_trace_entries.wr_idx = 0;
  600. if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
  601. fc_trace_entries.rd_idx++;
  602. if (fc_trace_entries.rd_idx >= fc_trace_max_entries)
  603. fc_trace_entries.rd_idx = 0;
  604. }
  605. ktime_get_real_ts64(&fc_buf->time_stamp);
  606. fc_buf->host_no = host_no;
  607. fc_buf->frame_type = frame_type;
  608. fc_trace = (char *)FC_TRACE_ADDRESS(fc_buf);
  609. /* During the receive path, we do not have eth hdr as well as fcoe hdr
  610. * at trace entry point so we will stuff 0xff just to make it generic.
  611. */
  612. if (frame_type == FNIC_FC_RECV) {
  613. eth_fcoe_hdr_len = sizeof(struct ethhdr) +
  614. sizeof(struct fcoe_hdr);
  615. memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
  616. /* Copy the rest of data frame */
  617. memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
  618. min_t(u8, fc_trc_frame_len,
  619. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
  620. - eth_fcoe_hdr_len)));
  621. } else {
  622. memcpy((char *)fc_trace, (void *)frame,
  623. min_t(u8, fc_trc_frame_len,
  624. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
  625. }
  626. /* Store the actual received length */
  627. fc_buf->frame_len = fc_trc_frame_len;
  628. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  629. return 0;
  630. }
  631. /*
  632. * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file
  633. * Passed parameter:
  634. * @fnic_dbgfs_t: pointer to debugfs trace buffer
  635. * rdata_flag: 1 => Unformatted file
  636. * 0 => formatted file
  637. * Description:
  638. * This routine will copy the trace data to memory file with
  639. * proper formatting and also copy to another memory
  640. * file without formatting for further processing.
  641. * Return Value:
  642. * Number of bytes that were dumped into fnic_dbgfs_t
  643. */
  644. int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag)
  645. {
  646. int rd_idx, wr_idx;
  647. unsigned long flags;
  648. int len = 0, j;
  649. struct fc_trace_hdr *tdata;
  650. char *fc_trace;
  651. spin_lock_irqsave(&fnic_fc_trace_lock, flags);
  652. if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
  653. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  654. pr_info("fnic: Buffer is empty\n");
  655. return 0;
  656. }
  657. rd_idx = fc_trace_entries.rd_idx;
  658. wr_idx = fc_trace_entries.wr_idx;
  659. if (rdata_flag == 0) {
  660. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  661. (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
  662. "Time Stamp (UTC)\t\t"
  663. "Host No: F Type: len: FCoE_FRAME:\n");
  664. }
  665. while (rd_idx != wr_idx) {
  666. tdata = (struct fc_trace_hdr *)
  667. fc_trace_entries.page_offset[rd_idx];
  668. if (!tdata) {
  669. pr_info("fnic: Rd data is NULL\n");
  670. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  671. return 0;
  672. }
  673. if (rdata_flag == 0) {
  674. copy_and_format_trace_data(tdata,
  675. fnic_dbgfs_prt, &len, rdata_flag);
  676. } else {
  677. fc_trace = (char *)tdata;
  678. for (j = 0; j < FC_TRC_SIZE_BYTES; j++) {
  679. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  680. (fnic_fc_trace_max_pages * PAGE_SIZE * 3)
  681. - len, "%02x", fc_trace[j] & 0xff);
  682. } /* for loop */
  683. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  684. (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
  685. "\n");
  686. }
  687. rd_idx++;
  688. if (rd_idx > (fc_trace_max_entries - 1))
  689. rd_idx = 0;
  690. }
  691. spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
  692. return len;
  693. }
  694. /*
  695. * copy_and_format_trace_data: Copy formatted data to char * buffer
  696. * Passed Parameter:
  697. * @fc_trace_hdr_t: pointer to trace data
  698. * @fnic_dbgfs_t: pointer to debugfs trace buffer
  699. * @orig_len: pointer to len
  700. * rdata_flag: 0 => Formatted file, 1 => Unformatted file
  701. * Description:
  702. * This routine will format and copy the passed trace data
  703. * for formatted file or unformatted file accordingly.
  704. */
  705. void copy_and_format_trace_data(struct fc_trace_hdr *tdata,
  706. fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len,
  707. u8 rdata_flag)
  708. {
  709. struct tm tm;
  710. int j, i = 1, len;
  711. char *fc_trace, *fmt;
  712. int ethhdr_len = sizeof(struct ethhdr) - 1;
  713. int fcoehdr_len = sizeof(struct fcoe_hdr);
  714. int fchdr_len = sizeof(struct fc_frame_header);
  715. int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3;
  716. tdata->frame_type = tdata->frame_type & 0x7F;
  717. len = *orig_len;
  718. time64_to_tm(tdata->time_stamp.tv_sec, 0, &tm);
  719. fmt = "%02d:%02d:%04ld %02d:%02d:%02d.%09lu ns%8x %c%8x\t";
  720. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  721. max_size - len,
  722. fmt,
  723. tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900,
  724. tm.tm_hour, tm.tm_min, tm.tm_sec,
  725. tdata->time_stamp.tv_nsec, tdata->host_no,
  726. tdata->frame_type, tdata->frame_len);
  727. fc_trace = (char *)FC_TRACE_ADDRESS(tdata);
  728. for (j = 0; j < min_t(u8, tdata->frame_len,
  729. (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) {
  730. if (tdata->frame_type == FNIC_FC_LE) {
  731. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  732. max_size - len, "%c", fc_trace[j]);
  733. } else {
  734. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  735. max_size - len, "%02x", fc_trace[j] & 0xff);
  736. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  737. max_size - len, " ");
  738. if (j == ethhdr_len ||
  739. j == ethhdr_len + fcoehdr_len ||
  740. j == ethhdr_len + fcoehdr_len + fchdr_len ||
  741. (i > 3 && j%fchdr_len == 0)) {
  742. len += scnprintf(fnic_dbgfs_prt->buffer
  743. + len, max_size - len,
  744. "\n\t\t\t\t\t\t\t\t");
  745. i++;
  746. }
  747. } /* end of else*/
  748. } /* End of for loop*/
  749. len += scnprintf(fnic_dbgfs_prt->buffer + len,
  750. max_size - len, "\n");
  751. *orig_len = len;
  752. }