1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/module.h>
19#include <linux/mempool.h>
20#include <linux/errno.h>
21#include <linux/spinlock.h>
22#include <linux/kallsyms.h>
23#include "fnic_io.h"
24#include "fnic.h"
25
26unsigned int trace_max_pages;
27static int fnic_max_trace_entries;
28
29static unsigned long fnic_trace_buf_p;
30static DEFINE_SPINLOCK(fnic_trace_lock);
31
32static fnic_trace_dbg_t fnic_trace_entries;
33int fnic_tracing_enabled = 1;
34
35
36
37
38
39
40
41
42
43
44
45
46
47fnic_trace_data_t *fnic_trace_get_buf(void)
48{
49 unsigned long fnic_buf_head;
50 unsigned long flags;
51
52 spin_lock_irqsave(&fnic_trace_lock, flags);
53
54
55
56
57
58 fnic_buf_head =
59 fnic_trace_entries.page_offset[fnic_trace_entries.wr_idx];
60 fnic_trace_entries.wr_idx++;
61
62
63
64
65
66 if (fnic_trace_entries.wr_idx >= fnic_max_trace_entries)
67 fnic_trace_entries.wr_idx = 0;
68
69
70
71
72
73 if (fnic_trace_entries.wr_idx == fnic_trace_entries.rd_idx) {
74 fnic_trace_entries.rd_idx++;
75 if (fnic_trace_entries.rd_idx >= fnic_max_trace_entries)
76 fnic_trace_entries.rd_idx = 0;
77 }
78 spin_unlock_irqrestore(&fnic_trace_lock, flags);
79 return (fnic_trace_data_t *)fnic_buf_head;
80}
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
96{
97 int rd_idx;
98 int wr_idx;
99 int len = 0;
100 unsigned long flags;
101 char str[KSYM_SYMBOL_LEN];
102 struct timespec val;
103 fnic_trace_data_t *tbp;
104
105 spin_lock_irqsave(&fnic_trace_lock, flags);
106 rd_idx = fnic_trace_entries.rd_idx;
107 wr_idx = fnic_trace_entries.wr_idx;
108 if (wr_idx < rd_idx) {
109 while (1) {
110
111 tbp = (fnic_trace_data_t *)
112 fnic_trace_entries.page_offset[rd_idx];
113 if (!tbp) {
114 spin_unlock_irqrestore(&fnic_trace_lock, flags);
115 return 0;
116 }
117
118 if (sizeof(unsigned long) < 8) {
119 sprint_symbol(str, tbp->fnaddr.low);
120 jiffies_to_timespec(tbp->timestamp.low, &val);
121 } else {
122 sprint_symbol(str, tbp->fnaddr.val);
123 jiffies_to_timespec(tbp->timestamp.val, &val);
124 }
125
126
127
128
129 len += snprintf(fnic_dbgfs_prt->buffer + len,
130 (trace_max_pages * PAGE_SIZE * 3) - len,
131 "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
132 "%16llx %16llx %16llx\n", val.tv_sec,
133 val.tv_nsec, str, tbp->host_no, tbp->tag,
134 tbp->data[0], tbp->data[1], tbp->data[2],
135 tbp->data[3], tbp->data[4]);
136 rd_idx++;
137
138
139
140
141 if (rd_idx > (fnic_max_trace_entries-1))
142 rd_idx = 0;
143
144
145
146
147 if (rd_idx == wr_idx)
148 break;
149 }
150 } else if (wr_idx > rd_idx) {
151 while (1) {
152
153 tbp = (fnic_trace_data_t *)
154 fnic_trace_entries.page_offset[rd_idx];
155 if (!tbp) {
156 spin_unlock_irqrestore(&fnic_trace_lock, flags);
157 return 0;
158 }
159
160 if (sizeof(unsigned long) < 8) {
161 sprint_symbol(str, tbp->fnaddr.low);
162 jiffies_to_timespec(tbp->timestamp.low, &val);
163 } else {
164 sprint_symbol(str, tbp->fnaddr.val);
165 jiffies_to_timespec(tbp->timestamp.val, &val);
166 }
167
168
169
170
171 len += snprintf(fnic_dbgfs_prt->buffer + len,
172 (trace_max_pages * PAGE_SIZE * 3) - len,
173 "%16lu.%16lu %-50s %8x %8x %16llx %16llx "
174 "%16llx %16llx %16llx\n", val.tv_sec,
175 val.tv_nsec, str, tbp->host_no, tbp->tag,
176 tbp->data[0], tbp->data[1], tbp->data[2],
177 tbp->data[3], tbp->data[4]);
178 rd_idx++;
179
180
181
182
183 if (rd_idx == wr_idx)
184 break;
185 }
186 }
187 spin_unlock_irqrestore(&fnic_trace_lock, flags);
188 return len;
189}
190
191
192
193
194
195
196
197
198
199int fnic_trace_buf_init(void)
200{
201 unsigned long fnic_buf_head;
202 int i;
203 int err = 0;
204
205 trace_max_pages = fnic_trace_max_pages;
206 fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
207 FNIC_ENTRY_SIZE_BYTES;
208
209 fnic_trace_buf_p = (unsigned long)vmalloc((trace_max_pages * PAGE_SIZE));
210 if (!fnic_trace_buf_p) {
211 printk(KERN_ERR PFX "Failed to allocate memory "
212 "for fnic_trace_buf_p\n");
213 err = -ENOMEM;
214 goto err_fnic_trace_buf_init;
215 }
216 memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE));
217
218 fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries *
219 sizeof(unsigned long));
220 if (!fnic_trace_entries.page_offset) {
221 printk(KERN_ERR PFX "Failed to allocate memory for"
222 " page_offset\n");
223 if (fnic_trace_buf_p) {
224 vfree((void *)fnic_trace_buf_p);
225 fnic_trace_buf_p = 0;
226 }
227 err = -ENOMEM;
228 goto err_fnic_trace_buf_init;
229 }
230 memset((void *)fnic_trace_entries.page_offset, 0,
231 (fnic_max_trace_entries * sizeof(unsigned long)));
232 fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0;
233 fnic_buf_head = fnic_trace_buf_p;
234
235
236
237
238
239
240 for (i = 0; i < fnic_max_trace_entries; i++) {
241 fnic_trace_entries.page_offset[i] = fnic_buf_head;
242 fnic_buf_head += FNIC_ENTRY_SIZE_BYTES;
243 }
244 err = fnic_trace_debugfs_init();
245 if (err < 0) {
246 printk(KERN_ERR PFX "Failed to initialize debugfs for tracing\n");
247 goto err_fnic_trace_debugfs_init;
248 }
249 printk(KERN_INFO PFX "Successfully Initialized Trace Buffer\n");
250 return err;
251err_fnic_trace_debugfs_init:
252 fnic_trace_free();
253err_fnic_trace_buf_init:
254 return err;
255}
256
257
258
259
260void fnic_trace_free(void)
261{
262 fnic_tracing_enabled = 0;
263 fnic_trace_debugfs_terminate();
264 if (fnic_trace_entries.page_offset) {
265 vfree((void *)fnic_trace_entries.page_offset);
266 fnic_trace_entries.page_offset = NULL;
267 }
268 if (fnic_trace_buf_p) {
269 vfree((void *)fnic_trace_buf_p);
270 fnic_trace_buf_p = 0;
271 }
272 printk(KERN_INFO PFX "Successfully Freed Trace Buffer\n");
273}
274