xref: /openbmc/linux/drivers/scsi/fnic/fnic_trace.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1e6550b3eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e6550b3eSThomas Gleixner // Copyright 2012 Cisco Systems, Inc.  All rights reserved.
34d7007b4SHiral Patel 
44d7007b4SHiral Patel #include <linux/module.h>
54d7007b4SHiral Patel #include <linux/mempool.h>
64d7007b4SHiral Patel #include <linux/errno.h>
74d7007b4SHiral Patel #include <linux/spinlock.h>
84d7007b4SHiral Patel #include <linux/kallsyms.h>
9abb14148SHiral Shah #include <linux/time.h>
10d6472302SStephen Rothwell #include <linux/vmalloc.h>
114d7007b4SHiral Patel #include "fnic_io.h"
124d7007b4SHiral Patel #include "fnic.h"
134d7007b4SHiral Patel 
144d7007b4SHiral Patel unsigned int trace_max_pages;
154d7007b4SHiral Patel static int fnic_max_trace_entries;
164d7007b4SHiral Patel 
174d7007b4SHiral Patel static unsigned long fnic_trace_buf_p;
184d7007b4SHiral Patel static DEFINE_SPINLOCK(fnic_trace_lock);
194d7007b4SHiral Patel 
204d7007b4SHiral Patel static fnic_trace_dbg_t fnic_trace_entries;
214d7007b4SHiral Patel int fnic_tracing_enabled = 1;
224d7007b4SHiral Patel 
23abb14148SHiral Shah /* static char *fnic_fc_ctlr_trace_buf_p; */
24abb14148SHiral Shah 
25abb14148SHiral Shah static int fc_trace_max_entries;
26abb14148SHiral Shah static unsigned long fnic_fc_ctlr_trace_buf_p;
27abb14148SHiral Shah static fnic_trace_dbg_t fc_trace_entries;
28abb14148SHiral Shah int fnic_fc_tracing_enabled = 1;
29abb14148SHiral Shah int fnic_fc_trace_cleared = 1;
30abb14148SHiral Shah static DEFINE_SPINLOCK(fnic_fc_trace_lock);
31abb14148SHiral Shah 
32abb14148SHiral Shah 
334d7007b4SHiral Patel /*
344d7007b4SHiral Patel  * fnic_trace_get_buf - Give buffer pointer to user to fill up trace information
354d7007b4SHiral Patel  *
364d7007b4SHiral Patel  * Description:
374d7007b4SHiral Patel  * This routine gets next available trace buffer entry location @wr_idx
384d7007b4SHiral Patel  * from allocated trace buffer pages and give that memory location
394d7007b4SHiral Patel  * to user to store the trace information.
404d7007b4SHiral Patel  *
414d7007b4SHiral Patel  * Return Value:
424d7007b4SHiral Patel  * This routine returns pointer to next available trace entry
434d7007b4SHiral Patel  * @fnic_buf_head for user to fill trace information.
444d7007b4SHiral Patel  */
fnic_trace_get_buf(void)454d7007b4SHiral Patel fnic_trace_data_t *fnic_trace_get_buf(void)
464d7007b4SHiral Patel {
474d7007b4SHiral Patel 	unsigned long fnic_buf_head;
484d7007b4SHiral Patel 	unsigned long flags;
494d7007b4SHiral Patel 
504d7007b4SHiral Patel 	spin_lock_irqsave(&fnic_trace_lock, flags);
514d7007b4SHiral Patel 
524d7007b4SHiral Patel 	/*
534d7007b4SHiral Patel 	 * Get next available memory location for writing trace information
544d7007b4SHiral Patel 	 * at @wr_idx and increment @wr_idx
554d7007b4SHiral Patel 	 */
564d7007b4SHiral Patel 	fnic_buf_head =
574d7007b4SHiral Patel 		fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx];
584d7007b4SHiral Patel 	fnic_trace_entries.wr_idx++;
594d7007b4SHiral Patel 
604d7007b4SHiral Patel 	/*
614d7007b4SHiral Patel 	 * Verify if trace buffer is full then change wd_idx to
624d7007b4SHiral Patel 	 * start from zero
634d7007b4SHiral Patel 	 */
644d7007b4SHiral Patel 	if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries)
654d7007b4SHiral Patel 		fnic_trace_entries.wr_idx = 0;
664d7007b4SHiral Patel 
674d7007b4SHiral Patel 	/*
684d7007b4SHiral Patel 	 * Verify if write index @wr_idx and read index @rd_idx are same then
694d7007b4SHiral Patel 	 * increment @rd_idx to move to next entry in trace buffer
704d7007b4SHiral Patel 	 */
714d7007b4SHiral Patel 	if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) {
724d7007b4SHiral Patel 		fnic_trace_entries.rd_idx++;
734d7007b4SHiral Patel 		if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries)
744d7007b4SHiral Patel 			fnic_trace_entries.rd_idx = 0;
754d7007b4SHiral Patel 	}
764d7007b4SHiral Patel 	spin_unlock_irqrestore(&fnic_trace_lock, flags);
774d7007b4SHiral Patel 	return (fnic_trace_data_t *)fnic_buf_head;
784d7007b4SHiral Patel }
794d7007b4SHiral Patel 
804d7007b4SHiral Patel /*
814d7007b4SHiral Patel  * fnic_get_trace_data - Copy trace buffer to a memory file
824d7007b4SHiral Patel  * @fnic_dbgfs_t: pointer to debugfs trace buffer
834d7007b4SHiral Patel  *
844d7007b4SHiral Patel  * Description:
854d7007b4SHiral Patel  * This routine gathers the fnic trace debugfs data from the fnic_trace_data_t
864d7007b4SHiral Patel  * buffer and dumps it to fnic_dbgfs_t. It will start at the rd_idx entry in
874d7007b4SHiral Patel  * the log and process the log until the end of the buffer. Then it will gather
884d7007b4SHiral Patel  * from the beginning of the log and process until the current entry @wr_idx.
894d7007b4SHiral Patel  *
904d7007b4SHiral Patel  * Return Value:
914d7007b4SHiral Patel  * This routine returns the amount of bytes that were dumped into fnic_dbgfs_t
924d7007b4SHiral Patel  */
fnic_get_trace_data(fnic_dbgfs_t * fnic_dbgfs_prt)934d7007b4SHiral Patel int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
944d7007b4SHiral Patel {
954d7007b4SHiral Patel 	int rd_idx;
964d7007b4SHiral Patel 	int wr_idx;
974d7007b4SHiral Patel 	int len = 0;
984d7007b4SHiral Patel 	unsigned long flags;
994d7007b4SHiral Patel 	char str[KSYM_SYMBOL_LEN];
10022807aa8SArnd Bergmann 	struct timespec64 val;
1014d7007b4SHiral Patel 	fnic_trace_data_t *tbp;
1024d7007b4SHiral Patel 
1034d7007b4SHiral Patel 	spin_lock_irqsave(&fnic_trace_lock, flags);
1044d7007b4SHiral Patel 	rd_idx = fnic_trace_entries.rd_idx;
1054d7007b4SHiral Patel 	wr_idx = fnic_trace_entries.wr_idx;
1064d7007b4SHiral Patel 	if (wr_idx < rd_idx) {
1074d7007b4SHiral Patel 		while (1) {
1084d7007b4SHiral Patel 			/* Start from read index @rd_idx */
1094d7007b4SHiral Patel 			tbp = (fnic_trace_data_t *)
1104d7007b4SHiral Patel 				  fnic_trace_entries.page_offset[rd_idx];
1114d7007b4SHiral Patel 			if (!tbp) {
1124d7007b4SHiral Patel 				spin_unlock_irqrestore(&fnic_trace_lock, flags);
1134d7007b4SHiral Patel 				return 0;
1144d7007b4SHiral Patel 			}
1154d7007b4SHiral Patel 			/* Convert function pointer to function name */
1164d7007b4SHiral Patel 			if (sizeof(unsigned long) < 8) {
1174d7007b4SHiral Patel 				sprint_symbol(str, tbp->fnaddr.low);
11822807aa8SArnd Bergmann 				jiffies_to_timespec64(tbp->timestamp.low, &val);
1194d7007b4SHiral Patel 			} else {
1204d7007b4SHiral Patel 				sprint_symbol(str, tbp->fnaddr.val);
12122807aa8SArnd Bergmann 				jiffies_to_timespec64(tbp->timestamp.val, &val);
1224d7007b4SHiral Patel 			}
1234d7007b4SHiral Patel 			/*
1244d7007b4SHiral Patel 			 * Dump trace buffer entry to memory file
1254d7007b4SHiral Patel 			 * and increment read index @rd_idx
1264d7007b4SHiral Patel 			 */
1272605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
1284d7007b4SHiral Patel 				  (trace_max_pages * PAGE_SIZE * 3) - len,
12922807aa8SArnd Bergmann 				  "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
13022807aa8SArnd Bergmann 				  "%16llx %16llx %16llx\n", (u64)val.tv_sec,
1314d7007b4SHiral Patel 				  val.tv_nsec, str, tbp->host_no, tbp->tag,
1324d7007b4SHiral Patel 				  tbp->data[0], tbp->data[1], tbp->data[2],
1334d7007b4SHiral Patel 				  tbp->data[3], tbp->data[4]);
1344d7007b4SHiral Patel 			rd_idx++;
1354d7007b4SHiral Patel 			/*
1364d7007b4SHiral Patel 			 * If rd_idx is reached to maximum trace entries
1374d7007b4SHiral Patel 			 * then move rd_idx to zero
1384d7007b4SHiral Patel 			 */
1394d7007b4SHiral Patel 			if (rd_idx > (fnic_max_trace_entries-1))
1404d7007b4SHiral Patel 				rd_idx = 0;
1414d7007b4SHiral Patel 			/*
142bcf064bcSBhaskar Chowdhury 			 * Continue dumping trace buffer entries into
1434d7007b4SHiral Patel 			 * memory file till rd_idx reaches write index
1444d7007b4SHiral Patel 			 */
1454d7007b4SHiral Patel 			if (rd_idx == wr_idx)
1464d7007b4SHiral Patel 				break;
1474d7007b4SHiral Patel 		}
1484d7007b4SHiral Patel 	} else if (wr_idx > rd_idx) {
1494d7007b4SHiral Patel 		while (1) {
1504d7007b4SHiral Patel 			/* Start from read index @rd_idx */
1514d7007b4SHiral Patel 			tbp = (fnic_trace_data_t *)
1524d7007b4SHiral Patel 				  fnic_trace_entries.page_offset[rd_idx];
1534d7007b4SHiral Patel 			if (!tbp) {
1544d7007b4SHiral Patel 				spin_unlock_irqrestore(&fnic_trace_lock, flags);
1554d7007b4SHiral Patel 				return 0;
1564d7007b4SHiral Patel 			}
1574d7007b4SHiral Patel 			/* Convert function pointer to function name */
1584d7007b4SHiral Patel 			if (sizeof(unsigned long) < 8) {
1594d7007b4SHiral Patel 				sprint_symbol(str, tbp->fnaddr.low);
16022807aa8SArnd Bergmann 				jiffies_to_timespec64(tbp->timestamp.low, &val);
1614d7007b4SHiral Patel 			} else {
1624d7007b4SHiral Patel 				sprint_symbol(str, tbp->fnaddr.val);
16322807aa8SArnd Bergmann 				jiffies_to_timespec64(tbp->timestamp.val, &val);
1644d7007b4SHiral Patel 			}
1654d7007b4SHiral Patel 			/*
1664d7007b4SHiral Patel 			 * Dump trace buffer entry to memory file
1674d7007b4SHiral Patel 			 * and increment read index @rd_idx
1684d7007b4SHiral Patel 			 */
1692605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
1704d7007b4SHiral Patel 				  (trace_max_pages * PAGE_SIZE * 3) - len,
17122807aa8SArnd Bergmann 				  "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
17222807aa8SArnd Bergmann 				  "%16llx %16llx %16llx\n", (u64)val.tv_sec,
1734d7007b4SHiral Patel 				  val.tv_nsec, str, tbp->host_no, tbp->tag,
1744d7007b4SHiral Patel 				  tbp->data[0], tbp->data[1], tbp->data[2],
1754d7007b4SHiral Patel 				  tbp->data[3], tbp->data[4]);
1764d7007b4SHiral Patel 			rd_idx++;
1774d7007b4SHiral Patel 			/*
178bcf064bcSBhaskar Chowdhury 			 * Continue dumping trace buffer entries into
1794d7007b4SHiral Patel 			 * memory file till rd_idx reaches write index
1804d7007b4SHiral Patel 			 */
1814d7007b4SHiral Patel 			if (rd_idx == wr_idx)
1824d7007b4SHiral Patel 				break;
1834d7007b4SHiral Patel 		}
1844d7007b4SHiral Patel 	}
1854d7007b4SHiral Patel 	spin_unlock_irqrestore(&fnic_trace_lock, flags);
1864d7007b4SHiral Patel 	return len;
1874d7007b4SHiral Patel }
1884d7007b4SHiral Patel 
1894d7007b4SHiral Patel /*
19067125b02SHiral Patel  * fnic_get_stats_data - Copy fnic stats buffer to a memory file
19167125b02SHiral Patel  * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer
19267125b02SHiral Patel  *
19367125b02SHiral Patel  * Description:
19467125b02SHiral Patel  * This routine gathers the fnic stats debugfs data from the fnic_stats struct
19567125b02SHiral Patel  * and dumps it to stats_debug_info.
19667125b02SHiral Patel  *
19767125b02SHiral Patel  * Return Value:
19867125b02SHiral Patel  * This routine returns the amount of bytes that were dumped into
19967125b02SHiral Patel  * stats_debug_info
20067125b02SHiral Patel  */
fnic_get_stats_data(struct stats_debug_info * debug,struct fnic_stats * stats)20167125b02SHiral Patel int fnic_get_stats_data(struct stats_debug_info *debug,
20267125b02SHiral Patel 			struct fnic_stats *stats)
20367125b02SHiral Patel {
20467125b02SHiral Patel 	int len = 0;
20567125b02SHiral Patel 	int buf_size = debug->buf_size;
20622807aa8SArnd Bergmann 	struct timespec64 val1, val2;
20767125b02SHiral Patel 
20822807aa8SArnd Bergmann 	ktime_get_real_ts64(&val1);
2092605fbd8STakashi Iwai 	len = scnprintf(debug->debug_buffer + len, buf_size - len,
21067125b02SHiral Patel 		"------------------------------------------\n"
21143caa03fSSatish Kharat 		 "\t\tTime\n"
21243caa03fSSatish Kharat 		"------------------------------------------\n");
21343caa03fSSatish Kharat 
2142605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
21522807aa8SArnd Bergmann 		"Current time :          [%lld:%ld]\n"
21622807aa8SArnd Bergmann 		"Last stats reset time:  [%lld:%09ld]\n"
21722807aa8SArnd Bergmann 		"Last stats read time:   [%lld:%ld]\n"
21822807aa8SArnd Bergmann 		"delta since last reset: [%lld:%ld]\n"
21922807aa8SArnd Bergmann 		"delta since last read:  [%lld:%ld]\n",
22022807aa8SArnd Bergmann 	(s64)val1.tv_sec, val1.tv_nsec,
22122807aa8SArnd Bergmann 	(s64)stats->stats_timestamps.last_reset_time.tv_sec,
22243caa03fSSatish Kharat 	stats->stats_timestamps.last_reset_time.tv_nsec,
22322807aa8SArnd Bergmann 	(s64)stats->stats_timestamps.last_read_time.tv_sec,
22443caa03fSSatish Kharat 	stats->stats_timestamps.last_read_time.tv_nsec,
22522807aa8SArnd Bergmann 	(s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
22622807aa8SArnd Bergmann 	timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
22722807aa8SArnd Bergmann 	(s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
22822807aa8SArnd Bergmann 	timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
22943caa03fSSatish Kharat 
23043caa03fSSatish Kharat 	stats->stats_timestamps.last_read_time = val1;
23143caa03fSSatish Kharat 
2322605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
23343caa03fSSatish Kharat 		  "------------------------------------------\n"
23467125b02SHiral Patel 		  "\t\tIO Statistics\n"
23567125b02SHiral Patel 		  "------------------------------------------\n");
2362605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
23767125b02SHiral Patel 		  "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n"
23867125b02SHiral Patel 		  "Number of IOs: %lld\nNumber of IO Completions: %lld\n"
23967125b02SHiral Patel 		  "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
24067125b02SHiral Patel 		  "Number of Memory alloc Failures: %lld\n"
24167125b02SHiral Patel 		  "Number of IOREQ Null: %lld\n"
242445d2960SSatish Kharat 		  "Number of SCSI cmd pointer Null: %lld\n"
243445d2960SSatish Kharat 
244445d2960SSatish Kharat 		  "\nIO completion times: \n"
245445d2960SSatish Kharat 		  "            < 10 ms : %lld\n"
246445d2960SSatish Kharat 		  "     10 ms - 100 ms : %lld\n"
247445d2960SSatish Kharat 		  "    100 ms - 500 ms : %lld\n"
248445d2960SSatish Kharat 		  "    500 ms -   5 sec: %lld\n"
249445d2960SSatish Kharat 		  "     5 sec -  10 sec: %lld\n"
250445d2960SSatish Kharat 		  "    10 sec -  30 sec: %lld\n"
251445d2960SSatish Kharat 		  "            > 30 sec: %lld\n",
25267125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.active_ios),
25367125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.max_active_ios),
25467125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.num_ios),
25567125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.io_completions),
25667125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.io_failures),
25767125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.io_not_found),
25867125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.alloc_failures),
25967125b02SHiral Patel 		  (u64)atomic64_read(&stats->io_stats.ioreq_null),
260445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.sc_null),
261445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec),
262445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec),
263445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec),
264445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec),
265445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec),
266445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
267445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
268445d2960SSatish Kharat 
2692605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
270445d2960SSatish Kharat 		  "\nCurrent Max IO time : %lld\n",
271445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->io_stats.current_max_io_time));
27267125b02SHiral Patel 
2732605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
27467125b02SHiral Patel 		  "\n------------------------------------------\n"
27567125b02SHiral Patel 		  "\t\tAbort Statistics\n"
27667125b02SHiral Patel 		  "------------------------------------------\n");
277445d2960SSatish Kharat 
2782605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
27967125b02SHiral Patel 		  "Number of Aborts: %lld\n"
28067125b02SHiral Patel 		  "Number of Abort Failures: %lld\n"
28167125b02SHiral Patel 		  "Number of Abort Driver Timeouts: %lld\n"
28267125b02SHiral Patel 		  "Number of Abort FW Timeouts: %lld\n"
283445d2960SSatish Kharat 		  "Number of Abort IO NOT Found: %lld\n"
284445d2960SSatish Kharat 
2850cfce53aSColin Ian King 		  "Abort issued times: \n"
286445d2960SSatish Kharat 		  "            < 6 sec : %lld\n"
287445d2960SSatish Kharat 		  "     6 sec - 20 sec : %lld\n"
288445d2960SSatish Kharat 		  "    20 sec - 30 sec : %lld\n"
289445d2960SSatish Kharat 		  "    30 sec - 40 sec : %lld\n"
290445d2960SSatish Kharat 		  "    40 sec - 50 sec : %lld\n"
291445d2960SSatish Kharat 		  "    50 sec - 60 sec : %lld\n"
292445d2960SSatish Kharat 		  "            > 60 sec: %lld\n",
293445d2960SSatish Kharat 
29467125b02SHiral Patel 		  (u64)atomic64_read(&stats->abts_stats.aborts),
29567125b02SHiral Patel 		  (u64)atomic64_read(&stats->abts_stats.abort_failures),
29667125b02SHiral Patel 		  (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts),
29767125b02SHiral Patel 		  (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts),
298445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_io_not_found),
299445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec),
300445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec),
301445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec),
302445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec),
303445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec),
304445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec),
305445d2960SSatish Kharat 		  (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec));
30667125b02SHiral Patel 
3072605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
30867125b02SHiral Patel 		  "\n------------------------------------------\n"
30967125b02SHiral Patel 		  "\t\tTerminate Statistics\n"
31067125b02SHiral Patel 		  "------------------------------------------\n");
311445d2960SSatish Kharat 
3122605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
31367125b02SHiral Patel 		  "Number of Terminates: %lld\n"
31467125b02SHiral Patel 		  "Maximum Terminates: %lld\n"
31567125b02SHiral Patel 		  "Number of Terminate Driver Timeouts: %lld\n"
31667125b02SHiral Patel 		  "Number of Terminate FW Timeouts: %lld\n"
31767125b02SHiral Patel 		  "Number of Terminate IO NOT Found: %lld\n"
31867125b02SHiral Patel 		  "Number of Terminate Failures: %lld\n",
31967125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.terminates),
32067125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.max_terminates),
32167125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts),
32267125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts),
32367125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.terminate_io_not_found),
32467125b02SHiral Patel 		  (u64)atomic64_read(&stats->term_stats.terminate_failures));
32567125b02SHiral Patel 
3262605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
32767125b02SHiral Patel 		  "\n------------------------------------------\n"
32867125b02SHiral Patel 		  "\t\tReset Statistics\n"
32967125b02SHiral Patel 		  "------------------------------------------\n");
33067125b02SHiral Patel 
3312605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
33267125b02SHiral Patel 		  "Number of Device Resets: %lld\n"
33367125b02SHiral Patel 		  "Number of Device Reset Failures: %lld\n"
33467125b02SHiral Patel 		  "Number of Device Reset Aborts: %lld\n"
33567125b02SHiral Patel 		  "Number of Device Reset Timeouts: %lld\n"
33667125b02SHiral Patel 		  "Number of Device Reset Terminates: %lld\n"
33767125b02SHiral Patel 		  "Number of FW Resets: %lld\n"
33867125b02SHiral Patel 		  "Number of FW Reset Completions: %lld\n"
33967125b02SHiral Patel 		  "Number of FW Reset Failures: %lld\n"
34067125b02SHiral Patel 		  "Number of Fnic Reset: %lld\n"
34167125b02SHiral Patel 		  "Number of Fnic Reset Completions: %lld\n"
34267125b02SHiral Patel 		  "Number of Fnic Reset Failures: %lld\n",
34367125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.device_resets),
34467125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.device_reset_failures),
34567125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.device_reset_aborts),
34667125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts),
34767125b02SHiral Patel 		  (u64)atomic64_read(
34867125b02SHiral Patel 			  &stats->reset_stats.device_reset_terminates),
34967125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.fw_resets),
35067125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.fw_reset_completions),
35167125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.fw_reset_failures),
35267125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.fnic_resets),
35367125b02SHiral Patel 		  (u64)atomic64_read(
35467125b02SHiral Patel 			  &stats->reset_stats.fnic_reset_completions),
35567125b02SHiral Patel 		  (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures));
35667125b02SHiral Patel 
3572605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
35867125b02SHiral Patel 		  "\n------------------------------------------\n"
35967125b02SHiral Patel 		  "\t\tFirmware Statistics\n"
36067125b02SHiral Patel 		  "------------------------------------------\n");
36167125b02SHiral Patel 
3622605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
36367125b02SHiral Patel 		  "Number of Active FW Requests %lld\n"
36467125b02SHiral Patel 		  "Maximum FW Requests: %lld\n"
36567125b02SHiral Patel 		  "Number of FW out of resources: %lld\n"
36667125b02SHiral Patel 		  "Number of FW IO errors: %lld\n",
36767125b02SHiral Patel 		  (u64)atomic64_read(&stats->fw_stats.active_fw_reqs),
36867125b02SHiral Patel 		  (u64)atomic64_read(&stats->fw_stats.max_fw_reqs),
36967125b02SHiral Patel 		  (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources),
37067125b02SHiral Patel 		  (u64)atomic64_read(&stats->fw_stats.io_fw_errs));
37167125b02SHiral Patel 
3722605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
37367125b02SHiral Patel 		  "\n------------------------------------------\n"
37467125b02SHiral Patel 		  "\t\tVlan Discovery Statistics\n"
37567125b02SHiral Patel 		  "------------------------------------------\n");
37667125b02SHiral Patel 
3772605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
37867125b02SHiral Patel 		  "Number of Vlan Discovery Requests Sent %lld\n"
37967125b02SHiral Patel 		  "Vlan Response Received with no FCF VLAN ID: %lld\n"
38067125b02SHiral Patel 		  "No solicitations recvd after vlan set, expiry count: %lld\n"
38167125b02SHiral Patel 		  "Flogi rejects count: %lld\n",
38267125b02SHiral Patel 		  (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs),
38367125b02SHiral Patel 		  (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID),
38467125b02SHiral Patel 		  (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count),
38567125b02SHiral Patel 		  (u64)atomic64_read(&stats->vlan_stats.flogi_rejects));
38667125b02SHiral Patel 
3872605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
38867125b02SHiral Patel 		  "\n------------------------------------------\n"
38967125b02SHiral Patel 		  "\t\tOther Important Statistics\n"
39067125b02SHiral Patel 		  "------------------------------------------\n");
39167125b02SHiral Patel 
39222807aa8SArnd Bergmann 	jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1);
39322807aa8SArnd Bergmann 	jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
39467125b02SHiral Patel 
3952605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
39622807aa8SArnd Bergmann 		  "Last ISR time: %llu (%8llu.%09lu)\n"
39722807aa8SArnd Bergmann 		  "Last ACK time: %llu (%8llu.%09lu)\n"
3983567dca1SSatish Kharat 		  "Max ISR jiffies: %llu\n"
3993567dca1SSatish Kharat 		  "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
4003567dca1SSatish Kharat 		  "Corr. work done: %llu\n"
40167125b02SHiral Patel 		  "Number of ISRs: %lld\n"
40267125b02SHiral Patel 		  "Maximum CQ Entries: %lld\n"
40367125b02SHiral Patel 		  "Number of ACK index out of range: %lld\n"
40467125b02SHiral Patel 		  "Number of data count mismatch: %lld\n"
40567125b02SHiral Patel 		  "Number of FCPIO Timeouts: %lld\n"
40667125b02SHiral Patel 		  "Number of FCPIO Aborted: %lld\n"
40767125b02SHiral Patel 		  "Number of SGL Invalid: %lld\n"
40867125b02SHiral Patel 		  "Number of Copy WQ Alloc Failures for ABTs: %lld\n"
40967125b02SHiral Patel 		  "Number of Copy WQ Alloc Failures for Device Reset: %lld\n"
41067125b02SHiral Patel 		  "Number of Copy WQ Alloc Failures for IOs: %lld\n"
41167125b02SHiral Patel 		  "Number of no icmnd itmf Completions: %lld\n"
41239fcbbc0SSatish Kharat 		  "Number of Check Conditions encountered: %lld\n"
41367125b02SHiral Patel 		  "Number of QUEUE Fulls: %lld\n"
41467125b02SHiral Patel 		  "Number of rport not ready: %lld\n"
41567125b02SHiral Patel 		  "Number of receive frame errors: %lld\n",
41667125b02SHiral Patel 		  (u64)stats->misc_stats.last_isr_time,
41722807aa8SArnd Bergmann 		  (s64)val1.tv_sec, val1.tv_nsec,
41867125b02SHiral Patel 		  (u64)stats->misc_stats.last_ack_time,
41922807aa8SArnd Bergmann 		  (s64)val2.tv_sec, val2.tv_nsec,
4203567dca1SSatish Kharat 		  (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
4213567dca1SSatish Kharat 		  (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
4223567dca1SSatish Kharat 		  (u64)atomic64_read(&stats->misc_stats.corr_work_done),
42367125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.isr_count),
42467125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.max_cq_entries),
42567125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range),
42667125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.data_count_mismatch),
42767125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.fcpio_timeout),
42867125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.fcpio_aborted),
42967125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.sgl_invalid),
43067125b02SHiral Patel 		  (u64)atomic64_read(
43167125b02SHiral Patel 			  &stats->misc_stats.abts_cpwq_alloc_failures),
43267125b02SHiral Patel 		  (u64)atomic64_read(
43367125b02SHiral Patel 			  &stats->misc_stats.devrst_cpwq_alloc_failures),
43467125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures),
43567125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls),
43639fcbbc0SSatish Kharat 		  (u64)atomic64_read(&stats->misc_stats.check_condition),
43767125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.queue_fulls),
43867125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.rport_not_ready),
43967125b02SHiral Patel 		  (u64)atomic64_read(&stats->misc_stats.frame_errors));
44067125b02SHiral Patel 
4412605fbd8STakashi Iwai 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
44290302e95SJohn Pittman 			"Firmware reported port speed: %llu\n",
443d948e638SSatish Kharat 			(u64)atomic64_read(
444d948e638SSatish Kharat 				&stats->misc_stats.current_port_speed));
445d948e638SSatish Kharat 
44667125b02SHiral Patel 	return len;
44767125b02SHiral Patel 
44867125b02SHiral Patel }
44967125b02SHiral Patel 
45067125b02SHiral Patel /*
4514d7007b4SHiral Patel  * fnic_trace_buf_init - Initialize fnic trace buffer logging facility
4524d7007b4SHiral Patel  *
4534d7007b4SHiral Patel  * Description:
4544d7007b4SHiral Patel  * Initialize trace buffer data structure by allocating required memory and
4554d7007b4SHiral Patel  * setting page_offset information for every trace entry by adding trace entry
4564d7007b4SHiral Patel  * length to previous page_offset value.
4574d7007b4SHiral Patel  */
fnic_trace_buf_init(void)4584d7007b4SHiral Patel int fnic_trace_buf_init(void)
4594d7007b4SHiral Patel {
4604d7007b4SHiral Patel 	unsigned long fnic_buf_head;
4614d7007b4SHiral Patel 	int i;
4624d7007b4SHiral Patel 	int err = 0;
4634d7007b4SHiral Patel 
4644d7007b4SHiral Patel 	trace_max_pages = fnic_trace_max_pages;
4654d7007b4SHiral Patel 	fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
4664d7007b4SHiral Patel 					  FNIC_ENTRY_SIZE_BYTES;
4674d7007b4SHiral Patel 
468*b34c7dcaSJulia Lawall 	fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE);
4694d7007b4SHiral Patel 	if (!fnic_trace_buf_p) {
4704d7007b4SHiral Patel 		printk(KERN_ERR PFX "Failed to allocate memory "
4714d7007b4SHiral Patel 				  "for fnic_trace_buf_p\n");
4724d7007b4SHiral Patel 		err = -ENOMEM;
4734d7007b4SHiral Patel 		goto err_fnic_trace_buf_init;
4744d7007b4SHiral Patel 	}
4754d7007b4SHiral Patel 
47642bc47b3SKees Cook 	fnic_trace_entries.page_offset =
47742bc47b3SKees Cook 		vmalloc(array_size(fnic_max_trace_entries,
47842bc47b3SKees Cook 				   sizeof(unsigned long)));
4794d7007b4SHiral Patel 	if (!fnic_trace_entries.page_offset) {
4804d7007b4SHiral Patel 		printk(KERN_ERR PFX "Failed to allocate memory for"
4814d7007b4SHiral Patel 				  " page_offset\n");
4824d7007b4SHiral Patel 		if (fnic_trace_buf_p) {
4834d7007b4SHiral Patel 			vfree((void *)fnic_trace_buf_p);
4844d7007b4SHiral Patel 			fnic_trace_buf_p = 0;
4854d7007b4SHiral Patel 		}
4864d7007b4SHiral Patel 		err = -ENOMEM;
4874d7007b4SHiral Patel 		goto err_fnic_trace_buf_init;
4884d7007b4SHiral Patel 	}
4894d7007b4SHiral Patel 	memset((void *)fnic_trace_entries.page_offset, 0,
4904d7007b4SHiral Patel 		  (fnic_max_trace_entries * sizeof(unsigned long)));
4914d7007b4SHiral Patel 	fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
4924d7007b4SHiral Patel 	fnic_buf_head = fnic_trace_buf_p;
4934d7007b4SHiral Patel 
4944d7007b4SHiral Patel 	/*
4954d7007b4SHiral Patel 	 * Set page_offset field of fnic_trace_entries struct by
4964d7007b4SHiral Patel 	 * calculating memory location for every trace entry using
4974d7007b4SHiral Patel 	 * length of each trace entry
4984d7007b4SHiral Patel 	 */
4994d7007b4SHiral Patel 	for (i = 0; i < fnic_max_trace_entries; i++) {
5004d7007b4SHiral Patel 		fnic_trace_entries.page_offset[i] = fnic_buf_head;
5014d7007b4SHiral Patel 		fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
5024d7007b4SHiral Patel 	}
5031dbaa379SGreg Kroah-Hartman 	fnic_trace_debugfs_init();
504abb14148SHiral Shah 	pr_info("fnic: Successfully Initialized Trace Buffer\n");
5054d7007b4SHiral Patel 	return err;
5061dbaa379SGreg Kroah-Hartman 
5074d7007b4SHiral Patel err_fnic_trace_buf_init:
5084d7007b4SHiral Patel 	return err;
5094d7007b4SHiral Patel }
5104d7007b4SHiral Patel 
5114d7007b4SHiral Patel /*
5124d7007b4SHiral Patel  * fnic_trace_free - Free memory of fnic trace data structures.
5134d7007b4SHiral Patel  */
fnic_trace_free(void)5144d7007b4SHiral Patel void fnic_trace_free(void)
5154d7007b4SHiral Patel {
5164d7007b4SHiral Patel 	fnic_tracing_enabled = 0;
5174d7007b4SHiral Patel 	fnic_trace_debugfs_terminate();
5184d7007b4SHiral Patel 	if (fnic_trace_entries.page_offset) {
5194d7007b4SHiral Patel 		vfree((void *)fnic_trace_entries.page_offset);
5204d7007b4SHiral Patel 		fnic_trace_entries.page_offset = NULL;
5214d7007b4SHiral Patel 	}
5224d7007b4SHiral Patel 	if (fnic_trace_buf_p) {
5234d7007b4SHiral Patel 		vfree((void *)fnic_trace_buf_p);
5244d7007b4SHiral Patel 		fnic_trace_buf_p = 0;
5254d7007b4SHiral Patel 	}
5264d7007b4SHiral Patel 	printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
5274d7007b4SHiral Patel }
528abb14148SHiral Shah 
529abb14148SHiral Shah /*
530abb14148SHiral Shah  * fnic_fc_ctlr_trace_buf_init -
531abb14148SHiral Shah  * Initialize trace buffer to log fnic control frames
532abb14148SHiral Shah  * Description:
533abb14148SHiral Shah  * Initialize trace buffer data structure by allocating
534abb14148SHiral Shah  * required memory for trace data as well as for Indexes.
535abb14148SHiral Shah  * Frame size is 256 bytes and
536abb14148SHiral Shah  * memory is allocated for 1024 entries of 256 bytes.
537abb14148SHiral Shah  * Page_offset(Index) is set to the address of trace entry
538abb14148SHiral Shah  * and page_offset is initialized by adding frame size
539abb14148SHiral Shah  * to the previous page_offset entry.
540abb14148SHiral Shah  */
541abb14148SHiral Shah 
fnic_fc_trace_init(void)542abb14148SHiral Shah int fnic_fc_trace_init(void)
543abb14148SHiral Shah {
544abb14148SHiral Shah 	unsigned long fc_trace_buf_head;
545abb14148SHiral Shah 	int err = 0;
546abb14148SHiral Shah 	int i;
547abb14148SHiral Shah 
548abb14148SHiral Shah 	fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/
549abb14148SHiral Shah 				FC_TRC_SIZE_BYTES;
55042bc47b3SKees Cook 	fnic_fc_ctlr_trace_buf_p =
55142bc47b3SKees Cook 		(unsigned long)vmalloc(array_size(PAGE_SIZE,
55242bc47b3SKees Cook 						  fnic_fc_trace_max_pages));
553abb14148SHiral Shah 	if (!fnic_fc_ctlr_trace_buf_p) {
554abb14148SHiral Shah 		pr_err("fnic: Failed to allocate memory for "
555abb14148SHiral Shah 		       "FC Control Trace Buf\n");
556abb14148SHiral Shah 		err = -ENOMEM;
557abb14148SHiral Shah 		goto err_fnic_fc_ctlr_trace_buf_init;
558abb14148SHiral Shah 	}
559abb14148SHiral Shah 
560abb14148SHiral Shah 	memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
561abb14148SHiral Shah 			fnic_fc_trace_max_pages * PAGE_SIZE);
562abb14148SHiral Shah 
563abb14148SHiral Shah 	/* Allocate memory for page offset */
56442bc47b3SKees Cook 	fc_trace_entries.page_offset =
56542bc47b3SKees Cook 		vmalloc(array_size(fc_trace_max_entries,
56642bc47b3SKees Cook 				   sizeof(unsigned long)));
567abb14148SHiral Shah 	if (!fc_trace_entries.page_offset) {
568abb14148SHiral Shah 		pr_err("fnic:Failed to allocate memory for page_offset\n");
569abb14148SHiral Shah 		if (fnic_fc_ctlr_trace_buf_p) {
570abb14148SHiral Shah 			pr_err("fnic: Freeing FC Control Trace Buf\n");
571abb14148SHiral Shah 			vfree((void *)fnic_fc_ctlr_trace_buf_p);
572abb14148SHiral Shah 			fnic_fc_ctlr_trace_buf_p = 0;
573abb14148SHiral Shah 		}
574abb14148SHiral Shah 		err = -ENOMEM;
575abb14148SHiral Shah 		goto err_fnic_fc_ctlr_trace_buf_init;
576abb14148SHiral Shah 	}
577abb14148SHiral Shah 	memset((void *)fc_trace_entries.page_offset, 0,
578abb14148SHiral Shah 	       (fc_trace_max_entries * sizeof(unsigned long)));
579abb14148SHiral Shah 
580abb14148SHiral Shah 	fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
581abb14148SHiral Shah 	fc_trace_buf_head = fnic_fc_ctlr_trace_buf_p;
582abb14148SHiral Shah 
583abb14148SHiral Shah 	/*
584abb14148SHiral Shah 	* Set up fc_trace_entries.page_offset field with memory location
585abb14148SHiral Shah 	* for every trace entry
586abb14148SHiral Shah 	*/
587abb14148SHiral Shah 	for (i = 0; i < fc_trace_max_entries; i++) {
588abb14148SHiral Shah 		fc_trace_entries.page_offset[i] = fc_trace_buf_head;
589abb14148SHiral Shah 		fc_trace_buf_head += FC_TRC_SIZE_BYTES;
590abb14148SHiral Shah 	}
5911dbaa379SGreg Kroah-Hartman 	fnic_fc_trace_debugfs_init();
592abb14148SHiral Shah 	pr_info("fnic: Successfully Initialized FC_CTLR Trace Buffer\n");
593abb14148SHiral Shah 	return err;
594abb14148SHiral Shah 
595abb14148SHiral Shah err_fnic_fc_ctlr_trace_buf_init:
596abb14148SHiral Shah 	return err;
597abb14148SHiral Shah }
598abb14148SHiral Shah 
599abb14148SHiral Shah /*
600abb14148SHiral Shah  * Fnic_fc_ctlr_trace_free - Free memory of fnic_fc_ctlr trace data structures.
601abb14148SHiral Shah  */
fnic_fc_trace_free(void)602abb14148SHiral Shah void fnic_fc_trace_free(void)
603abb14148SHiral Shah {
604abb14148SHiral Shah 	fnic_fc_tracing_enabled = 0;
605abb14148SHiral Shah 	fnic_fc_trace_debugfs_terminate();
606abb14148SHiral Shah 	if (fc_trace_entries.page_offset) {
607abb14148SHiral Shah 		vfree((void *)fc_trace_entries.page_offset);
608abb14148SHiral Shah 		fc_trace_entries.page_offset = NULL;
609abb14148SHiral Shah 	}
610abb14148SHiral Shah 	if (fnic_fc_ctlr_trace_buf_p) {
611abb14148SHiral Shah 		vfree((void *)fnic_fc_ctlr_trace_buf_p);
612abb14148SHiral Shah 		fnic_fc_ctlr_trace_buf_p = 0;
613abb14148SHiral Shah 	}
614abb14148SHiral Shah 	pr_info("fnic:Successfully FC_CTLR Freed Trace Buffer\n");
615abb14148SHiral Shah }
616abb14148SHiral Shah 
617abb14148SHiral Shah /*
618abb14148SHiral Shah  * fnic_fc_ctlr_set_trace_data:
619abb14148SHiral Shah  *       Maintain rd & wr idx accordingly and set data
620abb14148SHiral Shah  * Passed parameters:
621bcf064bcSBhaskar Chowdhury  *       host_no: host number associated with fnic
622abb14148SHiral Shah  *       frame_type: send_frame, rece_frame or link event
623abb14148SHiral Shah  *       fc_frame: pointer to fc_frame
624abb14148SHiral Shah  *       frame_len: Length of the fc_frame
625abb14148SHiral Shah  * Description:
626abb14148SHiral Shah  *   This routine will get next available wr_idx and
627abb14148SHiral Shah  *   copy all passed trace data to the buffer pointed by wr_idx
628abb14148SHiral Shah  *   and increment wr_idx. It will also make sure that we dont
629abb14148SHiral Shah  *   overwrite the entry which we are reading and also
630abb14148SHiral Shah  *   wrap around if we reach the maximum entries.
631abb14148SHiral Shah  * Returned Value:
632abb14148SHiral Shah  *   It will return 0 for success or -1 for failure
633abb14148SHiral Shah  */
fnic_fc_trace_set_data(u32 host_no,u8 frame_type,char * frame,u32 fc_trc_frame_len)634abb14148SHiral Shah int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
635abb14148SHiral Shah 				char *frame, u32 fc_trc_frame_len)
636abb14148SHiral Shah {
637abb14148SHiral Shah 	unsigned long flags;
638abb14148SHiral Shah 	struct fc_trace_hdr *fc_buf;
639abb14148SHiral Shah 	unsigned long eth_fcoe_hdr_len;
640abb14148SHiral Shah 	char *fc_trace;
641abb14148SHiral Shah 
642abb14148SHiral Shah 	if (fnic_fc_tracing_enabled == 0)
643abb14148SHiral Shah 		return 0;
644abb14148SHiral Shah 
645abb14148SHiral Shah 	spin_lock_irqsave(&fnic_fc_trace_lock, flags);
646abb14148SHiral Shah 
647abb14148SHiral Shah 	if (fnic_fc_trace_cleared == 1) {
648abb14148SHiral Shah 		fc_trace_entries.rd_idx = fc_trace_entries.wr_idx = 0;
6491a84db56SMasanari Iida 		pr_info("fnic: Resetting the read idx\n");
650abb14148SHiral Shah 		memset((void *)fnic_fc_ctlr_trace_buf_p, 0,
651abb14148SHiral Shah 				fnic_fc_trace_max_pages * PAGE_SIZE);
652abb14148SHiral Shah 		fnic_fc_trace_cleared = 0;
653abb14148SHiral Shah 	}
654abb14148SHiral Shah 
655abb14148SHiral Shah 	fc_buf = (struct fc_trace_hdr *)
656abb14148SHiral Shah 		fc_trace_entries.page_offset[fc_trace_entries.wr_idx];
657abb14148SHiral Shah 
658abb14148SHiral Shah 	fc_trace_entries.wr_idx++;
659abb14148SHiral Shah 
660abb14148SHiral Shah 	if (fc_trace_entries.wr_idx >= fc_trace_max_entries)
661abb14148SHiral Shah 		fc_trace_entries.wr_idx = 0;
662abb14148SHiral Shah 
663abb14148SHiral Shah 	if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
664abb14148SHiral Shah 		fc_trace_entries.rd_idx++;
665abb14148SHiral Shah 		if (fc_trace_entries.rd_idx >= fc_trace_max_entries)
666abb14148SHiral Shah 			fc_trace_entries.rd_idx = 0;
667abb14148SHiral Shah 	}
668abb14148SHiral Shah 
66948c4676dSDeepa Dinamani 	ktime_get_real_ts64(&fc_buf->time_stamp);
670abb14148SHiral Shah 	fc_buf->host_no = host_no;
671abb14148SHiral Shah 	fc_buf->frame_type = frame_type;
672abb14148SHiral Shah 
673abb14148SHiral Shah 	fc_trace = (char *)FC_TRACE_ADDRESS(fc_buf);
674abb14148SHiral Shah 
675abb14148SHiral Shah 	/* During the receive path, we do not have eth hdr as well as fcoe hdr
676abb14148SHiral Shah 	 * at trace entry point so we will stuff 0xff just to make it generic.
677abb14148SHiral Shah 	 */
678abb14148SHiral Shah 	if (frame_type == FNIC_FC_RECV) {
679abb14148SHiral Shah 		eth_fcoe_hdr_len = sizeof(struct ethhdr) +
680abb14148SHiral Shah 					sizeof(struct fcoe_hdr);
681abb14148SHiral Shah 		memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
682abb14148SHiral Shah 		/* Copy the rest of data frame */
683abb14148SHiral Shah 		memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
684abb14148SHiral Shah 		min_t(u8, fc_trc_frame_len,
685042b356aSHiral Shah 			(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
686042b356aSHiral Shah 						- eth_fcoe_hdr_len)));
687abb14148SHiral Shah 	} else {
688abb14148SHiral Shah 		memcpy((char *)fc_trace, (void *)frame,
689abb14148SHiral Shah 		min_t(u8, fc_trc_frame_len,
690abb14148SHiral Shah 			(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
691abb14148SHiral Shah 	}
692abb14148SHiral Shah 
693abb14148SHiral Shah 	/* Store the actual received length */
694abb14148SHiral Shah 	fc_buf->frame_len = fc_trc_frame_len;
695abb14148SHiral Shah 
696abb14148SHiral Shah 	spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
697abb14148SHiral Shah 	return 0;
698abb14148SHiral Shah }
699abb14148SHiral Shah 
700abb14148SHiral Shah /*
701abb14148SHiral Shah  * fnic_fc_ctlr_get_trace_data: Copy trace buffer to a memory file
702abb14148SHiral Shah  * Passed parameter:
703abb14148SHiral Shah  *       @fnic_dbgfs_t: pointer to debugfs trace buffer
704bcf064bcSBhaskar Chowdhury  *       rdata_flag: 1 => Unformatted file
705bcf064bcSBhaskar Chowdhury  *                   0 => formatted file
706abb14148SHiral Shah  * Description:
707abb14148SHiral Shah  *       This routine will copy the trace data to memory file with
708abb14148SHiral Shah  *       proper formatting and also copy to another memory
709bcf064bcSBhaskar Chowdhury  *       file without formatting for further processing.
710bcf064bcSBhaskar Chowdhury  * Return Value:
711abb14148SHiral Shah  *       Number of bytes that were dumped into fnic_dbgfs_t
712abb14148SHiral Shah  */
713abb14148SHiral Shah 
fnic_fc_trace_get_data(fnic_dbgfs_t * fnic_dbgfs_prt,u8 rdata_flag)714abb14148SHiral Shah int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag)
715abb14148SHiral Shah {
716abb14148SHiral Shah 	int rd_idx, wr_idx;
717abb14148SHiral Shah 	unsigned long flags;
718abb14148SHiral Shah 	int len = 0, j;
719abb14148SHiral Shah 	struct fc_trace_hdr *tdata;
720abb14148SHiral Shah 	char *fc_trace;
721abb14148SHiral Shah 
722abb14148SHiral Shah 	spin_lock_irqsave(&fnic_fc_trace_lock, flags);
723abb14148SHiral Shah 	if (fc_trace_entries.wr_idx == fc_trace_entries.rd_idx) {
724abb14148SHiral Shah 		spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
725abb14148SHiral Shah 		pr_info("fnic: Buffer is empty\n");
726abb14148SHiral Shah 		return 0;
727abb14148SHiral Shah 	}
728abb14148SHiral Shah 	rd_idx = fc_trace_entries.rd_idx;
729abb14148SHiral Shah 	wr_idx = fc_trace_entries.wr_idx;
730abb14148SHiral Shah 	if (rdata_flag == 0) {
7312605fbd8STakashi Iwai 		len += scnprintf(fnic_dbgfs_prt->buffer + len,
732abb14148SHiral Shah 			(fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
733abb14148SHiral Shah 			"Time Stamp (UTC)\t\t"
734abb14148SHiral Shah 			"Host No:   F Type:  len:     FCoE_FRAME:\n");
735abb14148SHiral Shah 	}
736abb14148SHiral Shah 
737abb14148SHiral Shah 	while (rd_idx != wr_idx) {
738abb14148SHiral Shah 		tdata = (struct fc_trace_hdr *)
739abb14148SHiral Shah 			fc_trace_entries.page_offset[rd_idx];
740abb14148SHiral Shah 		if (!tdata) {
741abb14148SHiral Shah 			pr_info("fnic: Rd data is NULL\n");
742abb14148SHiral Shah 			spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
743abb14148SHiral Shah 			return 0;
744abb14148SHiral Shah 		}
745abb14148SHiral Shah 		if (rdata_flag == 0) {
746abb14148SHiral Shah 			copy_and_format_trace_data(tdata,
747abb14148SHiral Shah 				fnic_dbgfs_prt, &len, rdata_flag);
748abb14148SHiral Shah 		} else {
749abb14148SHiral Shah 			fc_trace = (char *)tdata;
750abb14148SHiral Shah 			for (j = 0; j < FC_TRC_SIZE_BYTES; j++) {
7512605fbd8STakashi Iwai 				len += scnprintf(fnic_dbgfs_prt->buffer + len,
752abb14148SHiral Shah 				(fnic_fc_trace_max_pages * PAGE_SIZE * 3)
753abb14148SHiral Shah 				- len, "%02x", fc_trace[j] & 0xff);
754abb14148SHiral Shah 			} /* for loop */
7552605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
756abb14148SHiral Shah 				(fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
757abb14148SHiral Shah 				"\n");
758abb14148SHiral Shah 		}
759abb14148SHiral Shah 		rd_idx++;
760abb14148SHiral Shah 		if (rd_idx > (fc_trace_max_entries - 1))
761abb14148SHiral Shah 			rd_idx = 0;
762abb14148SHiral Shah 	}
763abb14148SHiral Shah 
764abb14148SHiral Shah 	spin_unlock_irqrestore(&fnic_fc_trace_lock, flags);
765abb14148SHiral Shah 	return len;
766abb14148SHiral Shah }
767abb14148SHiral Shah 
768abb14148SHiral Shah /*
769abb14148SHiral Shah  * copy_and_format_trace_data: Copy formatted data to char * buffer
770abb14148SHiral Shah  * Passed Parameter:
771abb14148SHiral Shah  *      @fc_trace_hdr_t: pointer to trace data
772abb14148SHiral Shah  *      @fnic_dbgfs_t: pointer to debugfs trace buffer
773abb14148SHiral Shah  *      @orig_len: pointer to len
774bcf064bcSBhaskar Chowdhury  *      rdata_flag: 0 => Formatted file, 1 => Unformatted file
775abb14148SHiral Shah  * Description:
776abb14148SHiral Shah  *      This routine will format and copy the passed trace data
777bcf064bcSBhaskar Chowdhury  *      for formatted file or unformatted file accordingly.
778abb14148SHiral Shah  */
779abb14148SHiral Shah 
copy_and_format_trace_data(struct fc_trace_hdr * tdata,fnic_dbgfs_t * fnic_dbgfs_prt,int * orig_len,u8 rdata_flag)780abb14148SHiral Shah void copy_and_format_trace_data(struct fc_trace_hdr *tdata,
781abb14148SHiral Shah 				fnic_dbgfs_t *fnic_dbgfs_prt, int *orig_len,
782abb14148SHiral Shah 				u8 rdata_flag)
783abb14148SHiral Shah {
784abb14148SHiral Shah 	int j, i = 1, len;
785abb14148SHiral Shah 	int ethhdr_len = sizeof(struct ethhdr) - 1;
786abb14148SHiral Shah 	int fcoehdr_len = sizeof(struct fcoe_hdr);
787abb14148SHiral Shah 	int fchdr_len = sizeof(struct fc_frame_header);
788abb14148SHiral Shah 	int max_size = fnic_fc_trace_max_pages * PAGE_SIZE * 3;
78958b42c94SAndy Shevchenko 	char *fc_trace;
790abb14148SHiral Shah 
791abb14148SHiral Shah 	tdata->frame_type = tdata->frame_type & 0x7F;
792abb14148SHiral Shah 
793abb14148SHiral Shah 	len = *orig_len;
794abb14148SHiral Shah 
79558b42c94SAndy Shevchenko 	len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len,
79658b42c94SAndy Shevchenko 			 "%ptTs.%09lu ns%8x       %c%8x\t",
79758b42c94SAndy Shevchenko 			 &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec,
79858b42c94SAndy Shevchenko 			 tdata->host_no, tdata->frame_type, tdata->frame_len);
799abb14148SHiral Shah 
800abb14148SHiral Shah 	fc_trace = (char *)FC_TRACE_ADDRESS(tdata);
801abb14148SHiral Shah 
802abb14148SHiral Shah 	for (j = 0; j < min_t(u8, tdata->frame_len,
803abb14148SHiral Shah 		(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) {
804abb14148SHiral Shah 		if (tdata->frame_type == FNIC_FC_LE) {
8052605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
806abb14148SHiral Shah 				max_size - len, "%c", fc_trace[j]);
807abb14148SHiral Shah 		} else {
8082605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
809abb14148SHiral Shah 				max_size - len, "%02x", fc_trace[j] & 0xff);
8102605fbd8STakashi Iwai 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
811abb14148SHiral Shah 				max_size - len, " ");
812abb14148SHiral Shah 			if (j == ethhdr_len ||
813abb14148SHiral Shah 				j == ethhdr_len + fcoehdr_len ||
814abb14148SHiral Shah 				j == ethhdr_len + fcoehdr_len + fchdr_len ||
815abb14148SHiral Shah 				(i > 3 && j%fchdr_len == 0)) {
8162605fbd8STakashi Iwai 				len += scnprintf(fnic_dbgfs_prt->buffer
81786001f24SHiral Shah 					+ len, max_size - len,
818abb14148SHiral Shah 					"\n\t\t\t\t\t\t\t\t");
819abb14148SHiral Shah 				i++;
820abb14148SHiral Shah 			}
821abb14148SHiral Shah 		} /* end of else*/
822abb14148SHiral Shah 	} /* End of for loop*/
8232605fbd8STakashi Iwai 	len += scnprintf(fnic_dbgfs_prt->buffer + len,
824abb14148SHiral Shah 		max_size - len, "\n");
825abb14148SHiral Shah 	*orig_len = len;
826abb14148SHiral Shah }
827