1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright 2012 Cisco Systems, Inc. All rights reserved.
4 #include <linux/module.h>
5 #include <linux/mempool.h>
6 #include <linux/errno.h>
7 #include <linux/spinlock.h>
8 #include <linux/kallsyms.h>
9 #include <linux/time.h>
10 #include <linux/vmalloc.h>
14 unsigned int trace_max_pages
;
15 static int fnic_max_trace_entries
;
17 static unsigned long fnic_trace_buf_p
;
18 static DEFINE_SPINLOCK(fnic_trace_lock
);
20 static fnic_trace_dbg_t fnic_trace_entries
;
21 int fnic_tracing_enabled
= 1;
23 /* static char *fnic_fc_ctlr_trace_buf_p; */
25 static int fc_trace_max_entries
;
26 static unsigned long fnic_fc_ctlr_trace_buf_p
;
27 static fnic_trace_dbg_t fc_trace_entries
;
28 int fnic_fc_tracing_enabled
= 1;
29 int fnic_fc_trace_cleared
= 1;
30 static DEFINE_SPINLOCK(fnic_fc_trace_lock
);
34 * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
37 * This routine gets next available trace buffer entry location @wr_idx
38 * from allocated trace buffer pages and give that memory location
39 * to user to store the trace information.
42 * This routine returns pointer to next available trace entry
43 * @fnic_buf_head for user to fill trace information.
45 fnic_trace_data_t
*fnic_trace_get_buf(void)
47 unsigned long fnic_buf_head
;
50 spin_lock_irqsave(&fnic_trace_lock
, flags
);
53 * Get next available memory location for writing trace information
54 * at @wr_idx and increment @wr_idx
57 fnic_trace_entries
.page_offset
[fnic_trace_entries
.wr_idx
];
58 fnic_trace_entries
.wr_idx
++;
61 * Verify if trace buffer is full then change wd_idx to
64 if (fnic_trace_entries
.wr_idx
>= fnic_max_trace_entries
)
65 fnic_trace_entries
.wr_idx
= 0;
68 * Verify if write index @wr_idx and read index @rd_idx are same then
69 * increment @rd_idx to move to next entry in trace buffer
71 if (fnic_trace_entries
.wr_idx
== fnic_trace_entries
.rd_idx
) {
72 fnic_trace_entries
.rd_idx
++;
73 if (fnic_trace_entries
.rd_idx
>= fnic_max_trace_entries
)
74 fnic_trace_entries
.rd_idx
= 0;
76 spin_unlock_irqrestore(&fnic_trace_lock
, flags
);
77 return (fnic_trace_data_t
*)fnic_buf_head
;
81 * fnic_get_trace_data - Copy trace buffer to a memory file
82 * @fnic_dbgfs_t: pointer to debugfs trace buffer
85 * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t
86 * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in
87 * the log and process the log until the end of the buffer. Then it will gather
88 * from the beginning of the log and process until the current entry @wr_idx.
91 * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t
93 int fnic_get_trace_data(fnic_dbgfs_t
*fnic_dbgfs_prt
)
99 char str
[KSYM_SYMBOL_LEN
];
100 struct timespec64 val
;
101 fnic_trace_data_t
*tbp
;
103 spin_lock_irqsave(&fnic_trace_lock
, flags
);
104 rd_idx
= fnic_trace_entries
.rd_idx
;
105 wr_idx
= fnic_trace_entries
.wr_idx
;
106 if (wr_idx
< rd_idx
) {
108 /* Start from read index @rd_idx */
109 tbp
= (fnic_trace_data_t
*)
110 fnic_trace_entries
.page_offset
[rd_idx
];
112 spin_unlock_irqrestore(&fnic_trace_lock
, flags
);
115 /* Convert function pointer to function name */
116 if (sizeof(unsigned long) < 8) {
117 sprint_symbol(str
, tbp
->fnaddr
.low
);
118 jiffies_to_timespec64(tbp
->timestamp
.low
, &val
);
120 sprint_symbol(str
, tbp
->fnaddr
.val
);
121 jiffies_to_timespec64(tbp
->timestamp
.val
, &val
);
124 * Dump trace buffer entry to memory file
125 * and increment read index @rd_idx
127 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
128 (trace_max_pages
* PAGE_SIZE
* 3) - len
,
129 "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
130 "%16llx %16llx %16llx\n", (u64
)val
.tv_sec
,
131 val
.tv_nsec
, str
, tbp
->host_no
, tbp
->tag
,
132 tbp
->data
[0], tbp
->data
[1], tbp
->data
[2],
133 tbp
->data
[3], tbp
->data
[4]);
136 * If rd_idx is reached to maximum trace entries
137 * then move rd_idx to zero
139 if (rd_idx
> (fnic_max_trace_entries
-1))
142 * Continue dumping trace buffer entries into
143 * memory file till rd_idx reaches write index
145 if (rd_idx
== wr_idx
)
148 } else if (wr_idx
> rd_idx
) {
150 /* Start from read index @rd_idx */
151 tbp
= (fnic_trace_data_t
*)
152 fnic_trace_entries
.page_offset
[rd_idx
];
154 spin_unlock_irqrestore(&fnic_trace_lock
, flags
);
157 /* Convert function pointer to function name */
158 if (sizeof(unsigned long) < 8) {
159 sprint_symbol(str
, tbp
->fnaddr
.low
);
160 jiffies_to_timespec64(tbp
->timestamp
.low
, &val
);
162 sprint_symbol(str
, tbp
->fnaddr
.val
);
163 jiffies_to_timespec64(tbp
->timestamp
.val
, &val
);
166 * Dump trace buffer entry to memory file
167 * and increment read index @rd_idx
169 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
170 (trace_max_pages
* PAGE_SIZE
* 3) - len
,
171 "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
172 "%16llx %16llx %16llx\n", (u64
)val
.tv_sec
,
173 val
.tv_nsec
, str
, tbp
->host_no
, tbp
->tag
,
174 tbp
->data
[0], tbp
->data
[1], tbp
->data
[2],
175 tbp
->data
[3], tbp
->data
[4]);
178 * Continue dumping trace buffer entries into
179 * memory file till rd_idx reaches write index
181 if (rd_idx
== wr_idx
)
185 spin_unlock_irqrestore(&fnic_trace_lock
, flags
);
190 * fnic_get_stats_data - Copy fnic stats buffer to a memory file
191 * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer
194 * This routine gathers the fnic stats debugfs data from the fnic_stats struct
195 * and dumps it to stats_debug_info.
198 * This routine returns the amount of bytes that were dumped into
201 int fnic_get_stats_data(struct stats_debug_info
*debug
,
202 struct fnic_stats
*stats
)
205 int buf_size
= debug
->buf_size
;
206 struct timespec64 val1
, val2
;
209 ktime_get_real_ts64(&val1
);
210 len
= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
211 "------------------------------------------\n"
213 "------------------------------------------\n");
215 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
216 "Current time : [%lld:%ld]\n"
217 "Last stats reset time: [%lld:%09ld]\n"
218 "Last stats read time: [%lld:%ld]\n"
219 "delta since last reset: [%lld:%ld]\n"
220 "delta since last read: [%lld:%ld]\n",
221 (s64
)val1
.tv_sec
, val1
.tv_nsec
,
222 (s64
)stats
->stats_timestamps
.last_reset_time
.tv_sec
,
223 stats
->stats_timestamps
.last_reset_time
.tv_nsec
,
224 (s64
)stats
->stats_timestamps
.last_read_time
.tv_sec
,
225 stats
->stats_timestamps
.last_read_time
.tv_nsec
,
226 (s64
)timespec64_sub(val1
, stats
->stats_timestamps
.last_reset_time
).tv_sec
,
227 timespec64_sub(val1
, stats
->stats_timestamps
.last_reset_time
).tv_nsec
,
228 (s64
)timespec64_sub(val1
, stats
->stats_timestamps
.last_read_time
).tv_sec
,
229 timespec64_sub(val1
, stats
->stats_timestamps
.last_read_time
).tv_nsec
);
231 stats
->stats_timestamps
.last_read_time
= val1
;
233 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
234 "------------------------------------------\n"
235 "\t\tIO Statistics\n"
236 "------------------------------------------\n");
237 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
238 "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n"
239 "Number of IOs: %lld\nNumber of IO Completions: %lld\n"
240 "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
241 "Number of Memory alloc Failures: %lld\n"
242 "Number of IOREQ Null: %lld\n"
243 "Number of SCSI cmd pointer Null: %lld\n"
245 "\nIO completion times: \n"
247 " 10 ms - 100 ms : %lld\n"
248 " 100 ms - 500 ms : %lld\n"
249 " 500 ms - 5 sec: %lld\n"
250 " 5 sec - 10 sec: %lld\n"
251 " 10 sec - 30 sec: %lld\n"
253 (u64
)atomic64_read(&stats
->io_stats
.active_ios
),
254 (u64
)atomic64_read(&stats
->io_stats
.max_active_ios
),
255 (u64
)atomic64_read(&stats
->io_stats
.num_ios
),
256 (u64
)atomic64_read(&stats
->io_stats
.io_completions
),
257 (u64
)atomic64_read(&stats
->io_stats
.io_failures
),
258 (u64
)atomic64_read(&stats
->io_stats
.io_not_found
),
259 (u64
)atomic64_read(&stats
->io_stats
.alloc_failures
),
260 (u64
)atomic64_read(&stats
->io_stats
.ioreq_null
),
261 (u64
)atomic64_read(&stats
->io_stats
.sc_null
),
262 (u64
)atomic64_read(&stats
->io_stats
.io_btw_0_to_10_msec
),
263 (u64
)atomic64_read(&stats
->io_stats
.io_btw_10_to_100_msec
),
264 (u64
)atomic64_read(&stats
->io_stats
.io_btw_100_to_500_msec
),
265 (u64
)atomic64_read(&stats
->io_stats
.io_btw_500_to_5000_msec
),
266 (u64
)atomic64_read(&stats
->io_stats
.io_btw_5000_to_10000_msec
),
267 (u64
)atomic64_read(&stats
->io_stats
.io_btw_10000_to_30000_msec
),
268 (u64
)atomic64_read(&stats
->io_stats
.io_greater_than_30000_msec
));
270 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
271 "------------------------------------------\n"
272 "\t\tIO Queues and cumulative IOs\n"
273 "------------------------------------------\n");
275 for (i
= 0; i
< FNIC_MQ_MAX_QUEUES
; i
++) {
276 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
277 "Q:%d -> %lld\n", i
, (u64
)atomic64_read(&stats
->io_stats
.ios
[i
]));
280 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
281 "\nCurrent Max IO time : %lld\n",
282 (u64
)atomic64_read(&stats
->io_stats
.current_max_io_time
));
284 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
285 "\n------------------------------------------\n"
286 "\t\tAbort Statistics\n"
287 "------------------------------------------\n");
289 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
290 "Number of Aborts: %lld\n"
291 "Number of Abort Failures: %lld\n"
292 "Number of Abort Driver Timeouts: %lld\n"
293 "Number of Abort FW Timeouts: %lld\n"
294 "Number of Abort IO NOT Found: %lld\n"
296 "Abort issued times: \n"
298 " 6 sec - 20 sec : %lld\n"
299 " 20 sec - 30 sec : %lld\n"
300 " 30 sec - 40 sec : %lld\n"
301 " 40 sec - 50 sec : %lld\n"
302 " 50 sec - 60 sec : %lld\n"
305 (u64
)atomic64_read(&stats
->abts_stats
.aborts
),
306 (u64
)atomic64_read(&stats
->abts_stats
.abort_failures
),
307 (u64
)atomic64_read(&stats
->abts_stats
.abort_drv_timeouts
),
308 (u64
)atomic64_read(&stats
->abts_stats
.abort_fw_timeouts
),
309 (u64
)atomic64_read(&stats
->abts_stats
.abort_io_not_found
),
310 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_0_to_6_sec
),
311 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_6_to_20_sec
),
312 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_20_to_30_sec
),
313 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_30_to_40_sec
),
314 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_40_to_50_sec
),
315 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_btw_50_to_60_sec
),
316 (u64
)atomic64_read(&stats
->abts_stats
.abort_issued_greater_than_60_sec
));
318 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
319 "\n------------------------------------------\n"
320 "\t\tTerminate Statistics\n"
321 "------------------------------------------\n");
323 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
324 "Number of Terminates: %lld\n"
325 "Maximum Terminates: %lld\n"
326 "Number of Terminate Driver Timeouts: %lld\n"
327 "Number of Terminate FW Timeouts: %lld\n"
328 "Number of Terminate IO NOT Found: %lld\n"
329 "Number of Terminate Failures: %lld\n",
330 (u64
)atomic64_read(&stats
->term_stats
.terminates
),
331 (u64
)atomic64_read(&stats
->term_stats
.max_terminates
),
332 (u64
)atomic64_read(&stats
->term_stats
.terminate_drv_timeouts
),
333 (u64
)atomic64_read(&stats
->term_stats
.terminate_fw_timeouts
),
334 (u64
)atomic64_read(&stats
->term_stats
.terminate_io_not_found
),
335 (u64
)atomic64_read(&stats
->term_stats
.terminate_failures
));
337 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
338 "\n------------------------------------------\n"
339 "\t\tReset Statistics\n"
340 "------------------------------------------\n");
342 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
343 "Number of Device Resets: %lld\n"
344 "Number of Device Reset Failures: %lld\n"
345 "Number of Device Reset Aborts: %lld\n"
346 "Number of Device Reset Timeouts: %lld\n"
347 "Number of Device Reset Terminates: %lld\n"
348 "Number of FW Resets: %lld\n"
349 "Number of FW Reset Completions: %lld\n"
350 "Number of FW Reset Failures: %lld\n"
351 "Number of Fnic Reset: %lld\n"
352 "Number of Fnic Reset Completions: %lld\n"
353 "Number of Fnic Reset Failures: %lld\n",
354 (u64
)atomic64_read(&stats
->reset_stats
.device_resets
),
355 (u64
)atomic64_read(&stats
->reset_stats
.device_reset_failures
),
356 (u64
)atomic64_read(&stats
->reset_stats
.device_reset_aborts
),
357 (u64
)atomic64_read(&stats
->reset_stats
.device_reset_timeouts
),
359 &stats
->reset_stats
.device_reset_terminates
),
360 (u64
)atomic64_read(&stats
->reset_stats
.fw_resets
),
361 (u64
)atomic64_read(&stats
->reset_stats
.fw_reset_completions
),
362 (u64
)atomic64_read(&stats
->reset_stats
.fw_reset_failures
),
363 (u64
)atomic64_read(&stats
->reset_stats
.fnic_resets
),
365 &stats
->reset_stats
.fnic_reset_completions
),
366 (u64
)atomic64_read(&stats
->reset_stats
.fnic_reset_failures
));
368 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
369 "\n------------------------------------------\n"
370 "\t\tFirmware Statistics\n"
371 "------------------------------------------\n");
373 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
374 "Number of Active FW Requests %lld\n"
375 "Maximum FW Requests: %lld\n"
376 "Number of FW out of resources: %lld\n"
377 "Number of FW IO errors: %lld\n",
378 (u64
)atomic64_read(&stats
->fw_stats
.active_fw_reqs
),
379 (u64
)atomic64_read(&stats
->fw_stats
.max_fw_reqs
),
380 (u64
)atomic64_read(&stats
->fw_stats
.fw_out_of_resources
),
381 (u64
)atomic64_read(&stats
->fw_stats
.io_fw_errs
));
383 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
384 "\n------------------------------------------\n"
385 "\t\tVlan Discovery Statistics\n"
386 "------------------------------------------\n");
388 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
389 "Number of Vlan Discovery Requests Sent %lld\n"
390 "Vlan Response Received with no FCF VLAN ID: %lld\n"
391 "No solicitations recvd after vlan set, expiry count: %lld\n"
392 "Flogi rejects count: %lld\n",
393 (u64
)atomic64_read(&stats
->vlan_stats
.vlan_disc_reqs
),
394 (u64
)atomic64_read(&stats
->vlan_stats
.resp_withno_vlanID
),
395 (u64
)atomic64_read(&stats
->vlan_stats
.sol_expiry_count
),
396 (u64
)atomic64_read(&stats
->vlan_stats
.flogi_rejects
));
398 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
399 "\n------------------------------------------\n"
400 "\t\tOther Important Statistics\n"
401 "------------------------------------------\n");
403 jiffies_to_timespec64(stats
->misc_stats
.last_isr_time
, &val1
);
404 jiffies_to_timespec64(stats
->misc_stats
.last_ack_time
, &val2
);
406 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
407 "Last ISR time: %llu (%8llu.%09lu)\n"
408 "Last ACK time: %llu (%8llu.%09lu)\n"
409 "Max ISR jiffies: %llu\n"
410 "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
411 "Corr. work done: %llu\n"
412 "Number of ISRs: %lld\n"
413 "Maximum CQ Entries: %lld\n"
414 "Number of ACK index out of range: %lld\n"
415 "Number of data count mismatch: %lld\n"
416 "Number of FCPIO Timeouts: %lld\n"
417 "Number of FCPIO Aborted: %lld\n"
418 "Number of SGL Invalid: %lld\n"
419 "Number of Copy WQ Alloc Failures for ABTs: %lld\n"
420 "Number of Copy WQ Alloc Failures for Device Reset: %lld\n"
421 "Number of Copy WQ Alloc Failures for IOs: %lld\n"
422 "Number of no icmnd itmf Completions: %lld\n"
423 "Number of Check Conditions encountered: %lld\n"
424 "Number of QUEUE Fulls: %lld\n"
425 "Number of rport not ready: %lld\n"
426 "Number of receive frame errors: %lld\n",
427 (u64
)stats
->misc_stats
.last_isr_time
,
428 (s64
)val1
.tv_sec
, val1
.tv_nsec
,
429 (u64
)stats
->misc_stats
.last_ack_time
,
430 (s64
)val2
.tv_sec
, val2
.tv_nsec
,
431 (u64
)atomic64_read(&stats
->misc_stats
.max_isr_jiffies
),
432 (u64
)atomic64_read(&stats
->misc_stats
.max_isr_time_ms
),
433 (u64
)atomic64_read(&stats
->misc_stats
.corr_work_done
),
434 (u64
)atomic64_read(&stats
->misc_stats
.isr_count
),
435 (u64
)atomic64_read(&stats
->misc_stats
.max_cq_entries
),
436 (u64
)atomic64_read(&stats
->misc_stats
.ack_index_out_of_range
),
437 (u64
)atomic64_read(&stats
->misc_stats
.data_count_mismatch
),
438 (u64
)atomic64_read(&stats
->misc_stats
.fcpio_timeout
),
439 (u64
)atomic64_read(&stats
->misc_stats
.fcpio_aborted
),
440 (u64
)atomic64_read(&stats
->misc_stats
.sgl_invalid
),
442 &stats
->misc_stats
.abts_cpwq_alloc_failures
),
444 &stats
->misc_stats
.devrst_cpwq_alloc_failures
),
445 (u64
)atomic64_read(&stats
->misc_stats
.io_cpwq_alloc_failures
),
446 (u64
)atomic64_read(&stats
->misc_stats
.no_icmnd_itmf_cmpls
),
447 (u64
)atomic64_read(&stats
->misc_stats
.check_condition
),
448 (u64
)atomic64_read(&stats
->misc_stats
.queue_fulls
),
449 (u64
)atomic64_read(&stats
->misc_stats
.rport_not_ready
),
450 (u64
)atomic64_read(&stats
->misc_stats
.frame_errors
));
452 len
+= scnprintf(debug
->debug_buffer
+ len
, buf_size
- len
,
453 "Firmware reported port speed: %llu\n",
455 &stats
->misc_stats
.current_port_speed
));
462 * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
465 * Initialize trace buffer data structure by allocating required memory and
466 * setting page_offset information for every trace entry by adding trace entry
467 * length to previous page_offset value.
469 int fnic_trace_buf_init(void)
471 unsigned long fnic_buf_head
;
475 trace_max_pages
= fnic_trace_max_pages
;
476 fnic_max_trace_entries
= (trace_max_pages
* PAGE_SIZE
)/
477 FNIC_ENTRY_SIZE_BYTES
;
479 fnic_trace_buf_p
= (unsigned long)vcalloc(trace_max_pages
, PAGE_SIZE
);
480 if (!fnic_trace_buf_p
) {
481 printk(KERN_ERR PFX
"Failed to allocate memory "
482 "for fnic_trace_buf_p\n");
484 goto err_fnic_trace_buf_init
;
487 fnic_trace_entries
.page_offset
=
488 vmalloc(array_size(fnic_max_trace_entries
,
489 sizeof(unsigned long)));
490 if (!fnic_trace_entries
.page_offset
) {
491 printk(KERN_ERR PFX
"Failed to allocate memory for"
493 if (fnic_trace_buf_p
) {
494 vfree((void *)fnic_trace_buf_p
);
495 fnic_trace_buf_p
= 0;
498 goto err_fnic_trace_buf_init
;
500 memset((void *)fnic_trace_entries
.page_offset
, 0,
501 (fnic_max_trace_entries
* sizeof(unsigned long)));
502 fnic_trace_entries
.wr_idx
= fnic_trace_entries
.rd_idx
= 0;
503 fnic_buf_head
= fnic_trace_buf_p
;
506 * Set page_offset field of fnic_trace_entries struct by
507 * calculating memory location for every trace entry using
508 * length of each trace entry
510 for (i
= 0; i
< fnic_max_trace_entries
; i
++) {
511 fnic_trace_entries
.page_offset
[i
] = fnic_buf_head
;
512 fnic_buf_head
+= FNIC_ENTRY_SIZE_BYTES
;
514 fnic_trace_debugfs_init();
515 pr_info("fnic: Successfully Initialized Trace Buffer\n");
518 err_fnic_trace_buf_init
:
523 * fnic_trace_free - Free memory of fnic trace data structures.
525 void fnic_trace_free(void)
527 fnic_tracing_enabled
= 0;
528 fnic_trace_debugfs_terminate();
529 if (fnic_trace_entries
.page_offset
) {
530 vfree((void *)fnic_trace_entries
.page_offset
);
531 fnic_trace_entries
.page_offset
= NULL
;
533 if (fnic_trace_buf_p
) {
534 vfree((void *)fnic_trace_buf_p
);
535 fnic_trace_buf_p
= 0;
537 printk(KERN_INFO PFX
"Successfully Freed Trace Buffer\n");
541 * fnic_fc_ctlr_trace_buf_init -
542 * Initialize trace buffer to log fnic control frames
544 * Initialize trace buffer data structure by allocating
545 * required memory for trace data as well as for Indexes.
546 * Frame size is 256 bytes and
547 * memory is allocated for 1024 entries of 256 bytes.
548 * Page_offset(Index) is set to the address of trace entry
549 * and page_offset is initialized by adding frame size
550 * to the previous page_offset entry.
553 int fnic_fc_trace_init(void)
555 unsigned long fc_trace_buf_head
;
559 fc_trace_max_entries
= (fnic_fc_trace_max_pages
* PAGE_SIZE
)/
561 fnic_fc_ctlr_trace_buf_p
=
562 (unsigned long)vmalloc(array_size(PAGE_SIZE
,
563 fnic_fc_trace_max_pages
));
564 if (!fnic_fc_ctlr_trace_buf_p
) {
565 pr_err("fnic: Failed to allocate memory for "
566 "FC Control Trace Buf\n");
568 goto err_fnic_fc_ctlr_trace_buf_init
;
571 memset((void *)fnic_fc_ctlr_trace_buf_p
, 0,
572 fnic_fc_trace_max_pages
* PAGE_SIZE
);
574 /* Allocate memory for page offset */
575 fc_trace_entries
.page_offset
=
576 vmalloc(array_size(fc_trace_max_entries
,
577 sizeof(unsigned long)));
578 if (!fc_trace_entries
.page_offset
) {
579 pr_err("fnic:Failed to allocate memory for page_offset\n");
580 if (fnic_fc_ctlr_trace_buf_p
) {
581 pr_err("fnic: Freeing FC Control Trace Buf\n");
582 vfree((void *)fnic_fc_ctlr_trace_buf_p
);
583 fnic_fc_ctlr_trace_buf_p
= 0;
586 goto err_fnic_fc_ctlr_trace_buf_init
;
588 memset((void *)fc_trace_entries
.page_offset
, 0,
589 (fc_trace_max_entries
* sizeof(unsigned long)));
591 fc_trace_entries
.rd_idx
= fc_trace_entries
.wr_idx
= 0;
592 fc_trace_buf_head
= fnic_fc_ctlr_trace_buf_p
;
595 * Set up fc_trace_entries.page_offset field with memory location
596 * for every trace entry
598 for (i
= 0; i
< fc_trace_max_entries
; i
++) {
599 fc_trace_entries
.page_offset
[i
] = fc_trace_buf_head
;
600 fc_trace_buf_head
+= FC_TRC_SIZE_BYTES
;
602 fnic_fc_trace_debugfs_init();
603 pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n");
606 err_fnic_fc_ctlr_trace_buf_init
:
611 * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures.
613 void fnic_fc_trace_free(void)
615 fnic_fc_tracing_enabled
= 0;
616 fnic_fc_trace_debugfs_terminate();
617 if (fc_trace_entries
.page_offset
) {
618 vfree((void *)fc_trace_entries
.page_offset
);
619 fc_trace_entries
.page_offset
= NULL
;
621 if (fnic_fc_ctlr_trace_buf_p
) {
622 vfree((void *)fnic_fc_ctlr_trace_buf_p
);
623 fnic_fc_ctlr_trace_buf_p
= 0;
625 pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n");
629 * fnic_fc_ctlr_set_trace_data:
630 * Maintain rd & wr idx accordingly and set data
632 * host_no: host number associated with fnic
633 * frame_type: send_frame, rece_frame or link event
634 * fc_frame: pointer to fc_frame
635 * frame_len: Length of the fc_frame
637 * This routine will get next available wr_idx and
638 * copy all passed trace data to the buffer pointed by wr_idx
639 * and increment wr_idx. It will also make sure that we dont
640 * overwrite the entry which we are reading and also
641 * wrap around if we reach the maximum entries.
643 * It will return 0 for success or -1 for failure
645 int fnic_fc_trace_set_data(u32 host_no
, u8 frame_type
,
646 char *frame
, u32 fc_trc_frame_len
)
649 struct fc_trace_hdr
*fc_buf
;
650 unsigned long eth_fcoe_hdr_len
;
653 if (fnic_fc_tracing_enabled
== 0)
656 spin_lock_irqsave(&fnic_fc_trace_lock
, flags
);
658 if (fnic_fc_trace_cleared
== 1) {
659 fc_trace_entries
.rd_idx
= fc_trace_entries
.wr_idx
= 0;
660 pr_info("fnic: Resetting the read idx\n");
661 memset((void *)fnic_fc_ctlr_trace_buf_p
, 0,
662 fnic_fc_trace_max_pages
* PAGE_SIZE
);
663 fnic_fc_trace_cleared
= 0;
666 fc_buf
= (struct fc_trace_hdr
*)
667 fc_trace_entries
.page_offset
[fc_trace_entries
.wr_idx
];
669 fc_trace_entries
.wr_idx
++;
671 if (fc_trace_entries
.wr_idx
>= fc_trace_max_entries
)
672 fc_trace_entries
.wr_idx
= 0;
674 if (fc_trace_entries
.wr_idx
== fc_trace_entries
.rd_idx
) {
675 fc_trace_entries
.rd_idx
++;
676 if (fc_trace_entries
.rd_idx
>= fc_trace_max_entries
)
677 fc_trace_entries
.rd_idx
= 0;
680 ktime_get_real_ts64(&fc_buf
->time_stamp
);
681 fc_buf
->host_no
= host_no
;
682 fc_buf
->frame_type
= frame_type
;
684 fc_trace
= (char *)FC_TRACE_ADDRESS(fc_buf
);
686 /* During the receive path, we do not have eth hdr as well as fcoe hdr
687 * at trace entry point so we will stuff 0xff just to make it generic.
689 if (frame_type
== FNIC_FC_RECV
) {
690 eth_fcoe_hdr_len
= sizeof(struct ethhdr
) +
691 sizeof(struct fcoe_hdr
);
692 memset((char *)fc_trace
, 0xff, eth_fcoe_hdr_len
);
693 /* Copy the rest of data frame */
694 memcpy((char *)(fc_trace
+ eth_fcoe_hdr_len
), (void *)frame
,
695 min_t(u8
, fc_trc_frame_len
,
696 (u8
)(FC_TRC_SIZE_BYTES
- FC_TRC_HEADER_SIZE
697 - eth_fcoe_hdr_len
)));
699 memcpy((char *)fc_trace
, (void *)frame
,
700 min_t(u8
, fc_trc_frame_len
,
701 (u8
)(FC_TRC_SIZE_BYTES
- FC_TRC_HEADER_SIZE
)));
704 /* Store the actual received length */
705 fc_buf
->frame_len
= fc_trc_frame_len
;
707 spin_unlock_irqrestore(&fnic_fc_trace_lock
, flags
);
712 * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file
714 * @fnic_dbgfs_t: pointer to debugfs trace buffer
715 * rdata_flag: 1 => Unformatted file
716 * 0 => formatted file
718 * This routine will copy the trace data to memory file with
719 * proper formatting and also copy to another memory
720 * file without formatting for further processing.
722 * Number of bytes that were dumped into fnic_dbgfs_t
725 int fnic_fc_trace_get_data(fnic_dbgfs_t
*fnic_dbgfs_prt
, u8 rdata_flag
)
730 struct fc_trace_hdr
*tdata
;
733 spin_lock_irqsave(&fnic_fc_trace_lock
, flags
);
734 if (fc_trace_entries
.wr_idx
== fc_trace_entries
.rd_idx
) {
735 spin_unlock_irqrestore(&fnic_fc_trace_lock
, flags
);
736 pr_info("fnic: Buffer is empty\n");
739 rd_idx
= fc_trace_entries
.rd_idx
;
740 wr_idx
= fc_trace_entries
.wr_idx
;
741 if (rdata_flag
== 0) {
742 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
743 (fnic_fc_trace_max_pages
* PAGE_SIZE
* 3) - len
,
744 "Time Stamp (UTC)\t\t"
745 "Host No: F Type: len: FCoE_FRAME:\n");
748 while (rd_idx
!= wr_idx
) {
749 tdata
= (struct fc_trace_hdr
*)
750 fc_trace_entries
.page_offset
[rd_idx
];
752 pr_info("fnic: Rd data is NULL\n");
753 spin_unlock_irqrestore(&fnic_fc_trace_lock
, flags
);
756 if (rdata_flag
== 0) {
757 copy_and_format_trace_data(tdata
,
758 fnic_dbgfs_prt
, &len
, rdata_flag
);
760 fc_trace
= (char *)tdata
;
761 for (j
= 0; j
< FC_TRC_SIZE_BYTES
; j
++) {
762 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
763 (fnic_fc_trace_max_pages
* PAGE_SIZE
* 3)
764 - len
, "%02x", fc_trace
[j
] & 0xff);
766 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
767 (fnic_fc_trace_max_pages
* PAGE_SIZE
* 3) - len
,
771 if (rd_idx
> (fc_trace_max_entries
- 1))
775 spin_unlock_irqrestore(&fnic_fc_trace_lock
, flags
);
780 * copy_and_format_trace_data: Copy formatted data to char * buffer
782 * @fc_trace_hdr_t: pointer to trace data
783 * @fnic_dbgfs_t: pointer to debugfs trace buffer
784 * @orig_len: pointer to len
785 * rdata_flag: 0 => Formatted file, 1 => Unformatted file
787 * This routine will format and copy the passed trace data
788 * for formatted file or unformatted file accordingly.
791 void copy_and_format_trace_data(struct fc_trace_hdr
*tdata
,
792 fnic_dbgfs_t
*fnic_dbgfs_prt
, int *orig_len
,
796 int ethhdr_len
= sizeof(struct ethhdr
) - 1;
797 int fcoehdr_len
= sizeof(struct fcoe_hdr
);
798 int fchdr_len
= sizeof(struct fc_frame_header
);
799 int max_size
= fnic_fc_trace_max_pages
* PAGE_SIZE
* 3;
802 tdata
->frame_type
= tdata
->frame_type
& 0x7F;
806 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
, max_size
- len
,
807 "%ptTs.%09lu ns%8x %c%8x\t",
808 &tdata
->time_stamp
.tv_sec
, tdata
->time_stamp
.tv_nsec
,
809 tdata
->host_no
, tdata
->frame_type
, tdata
->frame_len
);
811 fc_trace
= (char *)FC_TRACE_ADDRESS(tdata
);
813 for (j
= 0; j
< min_t(u8
, tdata
->frame_len
,
814 (u8
)(FC_TRC_SIZE_BYTES
- FC_TRC_HEADER_SIZE
)); j
++) {
815 if (tdata
->frame_type
== FNIC_FC_LE
) {
816 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
817 max_size
- len
, "%c", fc_trace
[j
]);
819 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
820 max_size
- len
, "%02x", fc_trace
[j
] & 0xff);
821 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
822 max_size
- len
, " ");
823 if (j
== ethhdr_len
||
824 j
== ethhdr_len
+ fcoehdr_len
||
825 j
== ethhdr_len
+ fcoehdr_len
+ fchdr_len
||
826 (i
> 3 && j
%fchdr_len
== 0)) {
827 len
+= scnprintf(fnic_dbgfs_prt
->buffer
828 + len
, max_size
- len
,
829 "\n\t\t\t\t\t\t\t\t");
833 } /* End of for loop*/
834 len
+= scnprintf(fnic_dbgfs_prt
->buffer
+ len
,
835 max_size
- len
, "\n");