aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_mmiotrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_mmiotrace.c')
-rw-r--r--kernel/trace/trace_mmiotrace.c153
1 files changed, 112 insertions, 41 deletions
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index b13dc19dcbb4..fffcb069f1dc 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -18,46 +18,39 @@ struct header_iter {
18 18
19static struct trace_array *mmio_trace_array; 19static struct trace_array *mmio_trace_array;
20static bool overrun_detected; 20static bool overrun_detected;
21static unsigned long prev_overruns;
21 22
22static void mmio_reset_data(struct trace_array *tr) 23static void mmio_reset_data(struct trace_array *tr)
23{ 24{
24 int cpu;
25
26 overrun_detected = false; 25 overrun_detected = false;
27 tr->time_start = ftrace_now(tr->cpu); 26 prev_overruns = 0;
28 27
29 for_each_online_cpu(cpu) 28 tracing_reset_online_cpus(tr);
30 tracing_reset(tr->data[cpu]);
31} 29}
32 30
33static void mmio_trace_init(struct trace_array *tr) 31static int mmio_trace_init(struct trace_array *tr)
34{ 32{
35 pr_debug("in %s\n", __func__); 33 pr_debug("in %s\n", __func__);
36 mmio_trace_array = tr; 34 mmio_trace_array = tr;
37 if (tr->ctrl) { 35
38 mmio_reset_data(tr); 36 mmio_reset_data(tr);
39 enable_mmiotrace(); 37 enable_mmiotrace();
40 } 38 return 0;
41} 39}
42 40
43static void mmio_trace_reset(struct trace_array *tr) 41static void mmio_trace_reset(struct trace_array *tr)
44{ 42{
45 pr_debug("in %s\n", __func__); 43 pr_debug("in %s\n", __func__);
46 if (tr->ctrl) 44
47 disable_mmiotrace(); 45 disable_mmiotrace();
48 mmio_reset_data(tr); 46 mmio_reset_data(tr);
49 mmio_trace_array = NULL; 47 mmio_trace_array = NULL;
50} 48}
51 49
52static void mmio_trace_ctrl_update(struct trace_array *tr) 50static void mmio_trace_start(struct trace_array *tr)
53{ 51{
54 pr_debug("in %s\n", __func__); 52 pr_debug("in %s\n", __func__);
55 if (tr->ctrl) { 53 mmio_reset_data(tr);
56 mmio_reset_data(tr);
57 enable_mmiotrace();
58 } else {
59 disable_mmiotrace();
60 }
61} 54}
62 55
63static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) 56static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
@@ -128,12 +121,12 @@ static void mmio_close(struct trace_iterator *iter)
128 121
129static unsigned long count_overruns(struct trace_iterator *iter) 122static unsigned long count_overruns(struct trace_iterator *iter)
130{ 123{
131 int cpu;
132 unsigned long cnt = 0; 124 unsigned long cnt = 0;
133 for_each_online_cpu(cpu) { 125 unsigned long over = ring_buffer_overruns(iter->tr->buffer);
134 cnt += iter->overrun[cpu]; 126
135 iter->overrun[cpu] = 0; 127 if (over > prev_overruns)
136 } 128 cnt = over - prev_overruns;
129 prev_overruns = over;
137 return cnt; 130 return cnt;
138} 131}
139 132
@@ -171,17 +164,21 @@ print_out:
171 return (ret == -EBUSY) ? 0 : ret; 164 return (ret == -EBUSY) ? 0 : ret;
172} 165}
173 166
174static int mmio_print_rw(struct trace_iterator *iter) 167static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
175{ 168{
176 struct trace_entry *entry = iter->ent; 169 struct trace_entry *entry = iter->ent;
177 struct mmiotrace_rw *rw = &entry->mmiorw; 170 struct trace_mmiotrace_rw *field;
171 struct mmiotrace_rw *rw;
178 struct trace_seq *s = &iter->seq; 172 struct trace_seq *s = &iter->seq;
179 unsigned long long t = ns2usecs(entry->t); 173 unsigned long long t = ns2usecs(iter->ts);
180 unsigned long usec_rem = do_div(t, 1000000ULL); 174 unsigned long usec_rem = do_div(t, 1000000ULL);
181 unsigned secs = (unsigned long)t; 175 unsigned secs = (unsigned long)t;
182 int ret = 1; 176 int ret = 1;
183 177
184 switch (entry->mmiorw.opcode) { 178 trace_assign_type(field, entry);
179 rw = &field->rw;
180
181 switch (rw->opcode) {
185 case MMIO_READ: 182 case MMIO_READ:
186 ret = trace_seq_printf(s, 183 ret = trace_seq_printf(s,
187 "R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 184 "R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
@@ -209,21 +206,25 @@ static int mmio_print_rw(struct trace_iterator *iter)
209 break; 206 break;
210 } 207 }
211 if (ret) 208 if (ret)
212 return 1; 209 return TRACE_TYPE_HANDLED;
213 return 0; 210 return TRACE_TYPE_PARTIAL_LINE;
214} 211}
215 212
216static int mmio_print_map(struct trace_iterator *iter) 213static enum print_line_t mmio_print_map(struct trace_iterator *iter)
217{ 214{
218 struct trace_entry *entry = iter->ent; 215 struct trace_entry *entry = iter->ent;
219 struct mmiotrace_map *m = &entry->mmiomap; 216 struct trace_mmiotrace_map *field;
217 struct mmiotrace_map *m;
220 struct trace_seq *s = &iter->seq; 218 struct trace_seq *s = &iter->seq;
221 unsigned long long t = ns2usecs(entry->t); 219 unsigned long long t = ns2usecs(iter->ts);
222 unsigned long usec_rem = do_div(t, 1000000ULL); 220 unsigned long usec_rem = do_div(t, 1000000ULL);
223 unsigned secs = (unsigned long)t; 221 unsigned secs = (unsigned long)t;
224 int ret = 1; 222 int ret;
225 223
226 switch (entry->mmiorw.opcode) { 224 trace_assign_type(field, entry);
225 m = &field->map;
226
227 switch (m->opcode) {
227 case MMIO_PROBE: 228 case MMIO_PROBE:
228 ret = trace_seq_printf(s, 229 ret = trace_seq_printf(s,
229 "MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n", 230 "MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
@@ -241,20 +242,43 @@ static int mmio_print_map(struct trace_iterator *iter)
241 break; 242 break;
242 } 243 }
243 if (ret) 244 if (ret)
244 return 1; 245 return TRACE_TYPE_HANDLED;
245 return 0; 246 return TRACE_TYPE_PARTIAL_LINE;
247}
248
249static enum print_line_t mmio_print_mark(struct trace_iterator *iter)
250{
251 struct trace_entry *entry = iter->ent;
252 struct print_entry *print = (struct print_entry *)entry;
253 const char *msg = print->buf;
254 struct trace_seq *s = &iter->seq;
255 unsigned long long t = ns2usecs(iter->ts);
256 unsigned long usec_rem = do_div(t, 1000000ULL);
257 unsigned secs = (unsigned long)t;
258 int ret;
259
260 /* The trailing newline must be in the message. */
261 ret = trace_seq_printf(s, "MARK %lu.%06lu %s", secs, usec_rem, msg);
262 if (!ret)
263 return TRACE_TYPE_PARTIAL_LINE;
264
265 if (entry->flags & TRACE_FLAG_CONT)
266 trace_seq_print_cont(s, iter);
267
268 return TRACE_TYPE_HANDLED;
246} 269}
247 270
248/* return 0 to abort printing without consuming current entry in pipe mode */ 271static enum print_line_t mmio_print_line(struct trace_iterator *iter)
249static int mmio_print_line(struct trace_iterator *iter)
250{ 272{
251 switch (iter->ent->type) { 273 switch (iter->ent->type) {
252 case TRACE_MMIO_RW: 274 case TRACE_MMIO_RW:
253 return mmio_print_rw(iter); 275 return mmio_print_rw(iter);
254 case TRACE_MMIO_MAP: 276 case TRACE_MMIO_MAP:
255 return mmio_print_map(iter); 277 return mmio_print_map(iter);
278 case TRACE_PRINT:
279 return mmio_print_mark(iter);
256 default: 280 default:
257 return 1; /* ignore unknown entries */ 281 return TRACE_TYPE_HANDLED; /* ignore unknown entries */
258 } 282 }
259} 283}
260 284
@@ -263,10 +287,10 @@ static struct tracer mmio_tracer __read_mostly =
263 .name = "mmiotrace", 287 .name = "mmiotrace",
264 .init = mmio_trace_init, 288 .init = mmio_trace_init,
265 .reset = mmio_trace_reset, 289 .reset = mmio_trace_reset,
290 .start = mmio_trace_start,
266 .pipe_open = mmio_pipe_open, 291 .pipe_open = mmio_pipe_open,
267 .close = mmio_close, 292 .close = mmio_close,
268 .read = mmio_read, 293 .read = mmio_read,
269 .ctrl_update = mmio_trace_ctrl_update,
270 .print_line = mmio_print_line, 294 .print_line = mmio_print_line,
271}; 295};
272 296
@@ -276,6 +300,27 @@ __init static int init_mmio_trace(void)
276} 300}
277device_initcall(init_mmio_trace); 301device_initcall(init_mmio_trace);
278 302
303static void __trace_mmiotrace_rw(struct trace_array *tr,
304 struct trace_array_cpu *data,
305 struct mmiotrace_rw *rw)
306{
307 struct ring_buffer_event *event;
308 struct trace_mmiotrace_rw *entry;
309 unsigned long irq_flags;
310
311 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
312 &irq_flags);
313 if (!event)
314 return;
315 entry = ring_buffer_event_data(event);
316 tracing_generic_entry_update(&entry->ent, 0, preempt_count());
317 entry->ent.type = TRACE_MMIO_RW;
318 entry->rw = *rw;
319 ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
320
321 trace_wake_up();
322}
323
279void mmio_trace_rw(struct mmiotrace_rw *rw) 324void mmio_trace_rw(struct mmiotrace_rw *rw)
280{ 325{
281 struct trace_array *tr = mmio_trace_array; 326 struct trace_array *tr = mmio_trace_array;
@@ -283,6 +328,27 @@ void mmio_trace_rw(struct mmiotrace_rw *rw)
283 __trace_mmiotrace_rw(tr, data, rw); 328 __trace_mmiotrace_rw(tr, data, rw);
284} 329}
285 330
331static void __trace_mmiotrace_map(struct trace_array *tr,
332 struct trace_array_cpu *data,
333 struct mmiotrace_map *map)
334{
335 struct ring_buffer_event *event;
336 struct trace_mmiotrace_map *entry;
337 unsigned long irq_flags;
338
339 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
340 &irq_flags);
341 if (!event)
342 return;
343 entry = ring_buffer_event_data(event);
344 tracing_generic_entry_update(&entry->ent, 0, preempt_count());
345 entry->ent.type = TRACE_MMIO_MAP;
346 entry->map = *map;
347 ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
348
349 trace_wake_up();
350}
351
286void mmio_trace_mapping(struct mmiotrace_map *map) 352void mmio_trace_mapping(struct mmiotrace_map *map)
287{ 353{
288 struct trace_array *tr = mmio_trace_array; 354 struct trace_array *tr = mmio_trace_array;
@@ -293,3 +359,8 @@ void mmio_trace_mapping(struct mmiotrace_map *map)
293 __trace_mmiotrace_map(tr, data, map); 359 __trace_mmiotrace_map(tr, data, map);
294 preempt_enable(); 360 preempt_enable();
295} 361}
362
363int mmio_trace_printk(const char *fmt, va_list args)
364{
365 return trace_vprintk(0, -1, fmt, args);
366}