xref: /linux/drivers/scsi/snic/snic_trc.c (revision 4d38b88fd17e9989429e65420bf3c33ca53b2085)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright 2014 Cisco Systems, Inc.  All rights reserved.
3 
4 #include <linux/module.h>
5 #include <linux/mempool.h>
6 #include <linux/errno.h>
7 #include <linux/vmalloc.h>
8 
9 #include "snic_io.h"
10 #include "snic.h"
11 
12 /*
13  * snic_get_trc_buf : Allocates a trace record and returns.
14  */
15 struct snic_trc_data *
snic_get_trc_buf(void)16 snic_get_trc_buf(void)
17 {
18 	struct snic_trc *trc = &snic_glob->trc;
19 	struct snic_trc_data *td = NULL;
20 	unsigned long flags;
21 
22 	spin_lock_irqsave(&trc->lock, flags);
23 	td = &trc->buf[trc->wr_idx];
24 	trc->wr_idx++;
25 
26 	if (trc->wr_idx == trc->max_idx)
27 		trc->wr_idx = 0;
28 
29 	if (trc->wr_idx != trc->rd_idx) {
30 		spin_unlock_irqrestore(&trc->lock, flags);
31 
32 		goto end;
33 	}
34 
35 	trc->rd_idx++;
36 	if (trc->rd_idx == trc->max_idx)
37 		trc->rd_idx = 0;
38 
39 	td->ts = 0;	/* Marker for checking the record, for complete data*/
40 	spin_unlock_irqrestore(&trc->lock, flags);
41 
42 end:
43 
44 	return td;
45 } /* end of snic_get_trc_buf */
46 
47 /*
48  * snic_fmt_trc_data : Formats trace data for printing.
49  */
50 static int
snic_fmt_trc_data(struct snic_trc_data * td,char * buf,int buf_sz)51 snic_fmt_trc_data(struct snic_trc_data *td, char *buf, int buf_sz)
52 {
53 	int len = 0;
54 	struct timespec64 tmspec;
55 
56 	jiffies_to_timespec64(td->ts, &tmspec);
57 
58 	len += snprintf(buf, buf_sz,
59 			"%ptSp %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
60 			&tmspec,
61 			td->fn,
62 			td->hno,
63 			td->tag,
64 			td->data[0], td->data[1], td->data[2], td->data[3],
65 			td->data[4]);
66 
67 	return len;
68 } /* end of snic_fmt_trc_data */
69 
70 /*
71  * snic_get_trc_data : Returns a formatted trace buffer.
72  */
73 int
snic_get_trc_data(char * buf,int buf_sz)74 snic_get_trc_data(char *buf, int buf_sz)
75 {
76 	struct snic_trc_data *td = NULL;
77 	struct snic_trc *trc = &snic_glob->trc;
78 	unsigned long flags;
79 
80 	spin_lock_irqsave(&trc->lock, flags);
81 	if (trc->rd_idx == trc->wr_idx) {
82 		spin_unlock_irqrestore(&trc->lock, flags);
83 
84 		return -1;
85 	}
86 	td = &trc->buf[trc->rd_idx];
87 
88 	if (td->ts == 0) {
89 		/* write in progress. */
90 		spin_unlock_irqrestore(&trc->lock, flags);
91 
92 		return -1;
93 	}
94 
95 	trc->rd_idx++;
96 	if (trc->rd_idx == trc->max_idx)
97 		trc->rd_idx = 0;
98 	spin_unlock_irqrestore(&trc->lock, flags);
99 
100 	return snic_fmt_trc_data(td, buf, buf_sz);
101 } /* end of snic_get_trc_data */
102 
103 /*
104  * snic_trc_init() : Configures Trace Functionality for snic.
105  */
106 int
snic_trc_init(void)107 snic_trc_init(void)
108 {
109 	struct snic_trc *trc = &snic_glob->trc;
110 	void *tbuf = NULL;
111 	int tbuf_sz = 0, ret;
112 
113 	tbuf_sz = (snic_trace_max_pages * PAGE_SIZE);
114 	tbuf = vzalloc(tbuf_sz);
115 	if (!tbuf) {
116 		SNIC_ERR("Failed to Allocate Trace Buffer Size. %d\n", tbuf_sz);
117 		SNIC_ERR("Trace Facility not enabled.\n");
118 		ret = -ENOMEM;
119 
120 		return ret;
121 	}
122 
123 	trc->buf = (struct snic_trc_data *) tbuf;
124 	spin_lock_init(&trc->lock);
125 
126 	snic_trc_debugfs_init();
127 
128 	trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ);
129 	trc->rd_idx = trc->wr_idx = 0;
130 	trc->enable = true;
131 	SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n",
132 		  tbuf_sz / PAGE_SIZE);
133 	ret = 0;
134 
135 	return ret;
136 } /* end of snic_trc_init */
137 
138 /*
139  * snic_trc_free : Releases the trace buffer and disables the tracing.
140  */
141 void
snic_trc_free(void)142 snic_trc_free(void)
143 {
144 	struct snic_trc *trc = &snic_glob->trc;
145 
146 	trc->enable = false;
147 	snic_trc_debugfs_term();
148 
149 	if (trc->buf) {
150 		vfree(trc->buf);
151 		trc->buf = NULL;
152 	}
153 
154 	SNIC_INFO("Trace Facility Disabled.\n");
155 } /* end of snic_trc_free */
156