1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2f984b51eSPekka Paalanen /* 3f984b51eSPekka Paalanen * Memory mapped I/O tracing 4f984b51eSPekka Paalanen * 5f984b51eSPekka Paalanen * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi> 6f984b51eSPekka Paalanen */ 7f984b51eSPekka Paalanen 8f984b51eSPekka Paalanen #define DEBUG 1 9f984b51eSPekka Paalanen 10f984b51eSPekka Paalanen #include <linux/kernel.h> 11f984b51eSPekka Paalanen #include <linux/mmiotrace.h> 1213829537SPekka Paalanen #include <linux/pci.h> 135a0e3ad6STejun Heo #include <linux/slab.h> 14a5dec557SLi Zefan #include <linux/time.h> 15a5dec557SLi Zefan 1660063497SArun Sharma #include <linux/atomic.h> 17f984b51eSPekka Paalanen 18f984b51eSPekka Paalanen #include "trace.h" 19f0868d1eSSteven Rostedt #include "trace_output.h" 20f984b51eSPekka Paalanen 21d0a7e8caSPekka Paalanen struct header_iter { 22d0a7e8caSPekka Paalanen struct pci_dev *dev; 23d0a7e8caSPekka Paalanen }; 24d0a7e8caSPekka Paalanen 25f984b51eSPekka Paalanen static struct trace_array *mmio_trace_array; 262039238bSPekka Paalanen static bool overrun_detected; 277ee1768dSPekka Paalanen static unsigned long prev_overruns; 28173ed24eSPekka Paalanen static atomic_t dropped_count; 29f984b51eSPekka Paalanen 30bd8ac686SPekka Paalanen static void mmio_reset_data(struct trace_array *tr) 31bd8ac686SPekka Paalanen { 322039238bSPekka Paalanen overrun_detected = false; 337ee1768dSPekka Paalanen prev_overruns = 0; 34bd8ac686SPekka Paalanen 351c5eb448SSteven Rostedt (VMware) tracing_reset_online_cpus(&tr->array_buffer); 36bd8ac686SPekka Paalanen } 37f984b51eSPekka Paalanen 381c80025aSFrederic Weisbecker static int mmio_trace_init(struct trace_array *tr) 39f984b51eSPekka Paalanen { 40f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 41f984b51eSPekka Paalanen mmio_trace_array = tr; 42c76f0694SSteven Rostedt 43bd8ac686SPekka Paalanen mmio_reset_data(tr); 44f984b51eSPekka Paalanen enable_mmiotrace(); 451c80025aSFrederic Weisbecker return 0; 46f984b51eSPekka Paalanen } 47f984b51eSPekka Paalanen 48f984b51eSPekka Paalanen static void mmio_trace_reset(struct trace_array *tr) 49f984b51eSPekka Paalanen { 50f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 51c76f0694SSteven Rostedt 52f984b51eSPekka Paalanen disable_mmiotrace(); 53bd8ac686SPekka Paalanen mmio_reset_data(tr); 54bd8ac686SPekka Paalanen mmio_trace_array = NULL; 55f984b51eSPekka Paalanen } 56f984b51eSPekka Paalanen 57bbf5b1a0SSteven Rostedt static void mmio_trace_start(struct trace_array *tr) 58f984b51eSPekka Paalanen { 59f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 60bd8ac686SPekka Paalanen mmio_reset_data(tr); 61bd8ac686SPekka Paalanen } 62bd8ac686SPekka Paalanen 63a72e10afSSteven Rostedt (Red Hat) static void mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) 6413829537SPekka Paalanen { 6513829537SPekka Paalanen int i; 6613829537SPekka Paalanen resource_size_t start, end; 6713829537SPekka Paalanen const struct pci_driver *drv = pci_dev_driver(dev); 6813829537SPekka Paalanen 69a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x", 7013829537SPekka Paalanen dev->bus->number, dev->devfn, 7113829537SPekka Paalanen dev->vendor, dev->device, dev->irq); 7213829537SPekka Paalanen for (i = 0; i < 7; i++) { 739a51933eSBjorn Helgaas start = dev->resource[i].start; 74a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, " %llx", 7513829537SPekka Paalanen (unsigned long long)(start | 7613829537SPekka Paalanen (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); 7713829537SPekka Paalanen } 7813829537SPekka Paalanen for (i = 0; i < 7; i++) { 799a51933eSBjorn Helgaas start = dev->resource[i].start; 809a51933eSBjorn Helgaas end = dev->resource[i].end; 81a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, " %llx", 8213829537SPekka Paalanen dev->resource[i].start < dev->resource[i].end ? 8313829537SPekka Paalanen (unsigned long long)(end - start) + 1 : 0); 8413829537SPekka Paalanen } 8513829537SPekka Paalanen if (drv) 86a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, " %s\n", drv->name); 8713829537SPekka Paalanen else 88a72e10afSSteven Rostedt (Red Hat) trace_seq_puts(s, " \n"); 8913829537SPekka Paalanen } 9013829537SPekka Paalanen 91d0a7e8caSPekka Paalanen static void destroy_header_iter(struct header_iter *hiter) 92bd8ac686SPekka Paalanen { 93d0a7e8caSPekka Paalanen if (!hiter) 94d0a7e8caSPekka Paalanen return; 95d0a7e8caSPekka Paalanen pci_dev_put(hiter->dev); 96d0a7e8caSPekka Paalanen kfree(hiter); 97d0a7e8caSPekka Paalanen } 98d0a7e8caSPekka Paalanen 99d0a7e8caSPekka Paalanen static void mmio_pipe_open(struct trace_iterator *iter) 100d0a7e8caSPekka Paalanen { 101d0a7e8caSPekka Paalanen struct header_iter *hiter; 102bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 10313829537SPekka Paalanen 104146c3442Szhangwei(Jovi) trace_seq_puts(s, "VERSION 20070824\n"); 10513829537SPekka Paalanen 106d0a7e8caSPekka Paalanen hiter = kzalloc(sizeof(*hiter), GFP_KERNEL); 107d0a7e8caSPekka Paalanen if (!hiter) 108d0a7e8caSPekka Paalanen return; 109d0a7e8caSPekka Paalanen 110d0a7e8caSPekka Paalanen hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 111d0a7e8caSPekka Paalanen iter->private = hiter; 112d0a7e8caSPekka Paalanen } 113d0a7e8caSPekka Paalanen 114d0a7e8caSPekka Paalanen /* XXX: This is not called when the pipe is closed! */ 115d0a7e8caSPekka Paalanen static void mmio_close(struct trace_iterator *iter) 116d0a7e8caSPekka Paalanen { 117d0a7e8caSPekka Paalanen struct header_iter *hiter = iter->private; 118d0a7e8caSPekka Paalanen destroy_header_iter(hiter); 119d0a7e8caSPekka Paalanen iter->private = NULL; 120d0a7e8caSPekka Paalanen } 121d0a7e8caSPekka Paalanen 1222039238bSPekka Paalanen static unsigned long count_overruns(struct trace_iterator *iter) 1232039238bSPekka Paalanen { 124173ed24eSPekka Paalanen unsigned long cnt = atomic_xchg(&dropped_count, 0); 1251c5eb448SSteven Rostedt (VMware) unsigned long over = ring_buffer_overruns(iter->array_buffer->buffer); 1267ee1768dSPekka Paalanen 1277ee1768dSPekka Paalanen if (over > prev_overruns) 128173ed24eSPekka Paalanen cnt += over - prev_overruns; 1297ee1768dSPekka Paalanen prev_overruns = over; 1302039238bSPekka Paalanen return cnt; 1312039238bSPekka Paalanen } 1322039238bSPekka Paalanen 133d0a7e8caSPekka Paalanen static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, 134d0a7e8caSPekka Paalanen char __user *ubuf, size_t cnt, loff_t *ppos) 135d0a7e8caSPekka Paalanen { 136d0a7e8caSPekka Paalanen ssize_t ret; 137d0a7e8caSPekka Paalanen struct header_iter *hiter = iter->private; 138d0a7e8caSPekka Paalanen struct trace_seq *s = &iter->seq; 1392039238bSPekka Paalanen unsigned long n; 1402039238bSPekka Paalanen 1412039238bSPekka Paalanen n = count_overruns(iter); 1422039238bSPekka Paalanen if (n) { 1432039238bSPekka Paalanen /* XXX: This is later than where events were lost. */ 1442039238bSPekka Paalanen trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n); 1452039238bSPekka Paalanen if (!overrun_detected) 146a395d6a7SJoe Perches pr_warn("mmiotrace has lost events\n"); 1472039238bSPekka Paalanen overrun_detected = true; 1482039238bSPekka Paalanen goto print_out; 1492039238bSPekka Paalanen } 150d0a7e8caSPekka Paalanen 151d0a7e8caSPekka Paalanen if (!hiter) 152d0a7e8caSPekka Paalanen return 0; 153d0a7e8caSPekka Paalanen 154d0a7e8caSPekka Paalanen mmio_print_pcidev(s, hiter->dev); 155d0a7e8caSPekka Paalanen hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev); 156d0a7e8caSPekka Paalanen 157d0a7e8caSPekka Paalanen if (!hiter->dev) { 158d0a7e8caSPekka Paalanen destroy_header_iter(hiter); 159d0a7e8caSPekka Paalanen iter->private = NULL; 160d0a7e8caSPekka Paalanen } 161d0a7e8caSPekka Paalanen 1622039238bSPekka Paalanen print_out: 163d0a7e8caSPekka Paalanen ret = trace_seq_to_user(s, ubuf, cnt); 164d0a7e8caSPekka Paalanen return (ret == -EBUSY) ? 0 : ret; 165bd8ac686SPekka Paalanen } 166bd8ac686SPekka Paalanen 16707f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_rw(struct trace_iterator *iter) 168bd8ac686SPekka Paalanen { 169bd8ac686SPekka Paalanen struct trace_entry *entry = iter->ent; 1707104f300SSteven Rostedt struct trace_mmiotrace_rw *field; 1717104f300SSteven Rostedt struct mmiotrace_rw *rw; 172bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 1733928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 174a5dec557SLi Zefan unsigned long usec_rem = do_div(t, USEC_PER_SEC); 175bd8ac686SPekka Paalanen unsigned secs = (unsigned long)t; 176bd8ac686SPekka Paalanen 1777104f300SSteven Rostedt trace_assign_type(field, entry); 1787104f300SSteven Rostedt rw = &field->rw; 1797104f300SSteven Rostedt 180777e208dSSteven Rostedt switch (rw->opcode) { 181bd8ac686SPekka Paalanen case MMIO_READ: 182a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, 1835e4abc98SSteven Rostedt "R %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 184dee310d0SPekka Paalanen rw->width, secs, usec_rem, rw->map_id, 185dee310d0SPekka Paalanen (unsigned long long)rw->phys, 186736ca61fSPekka Paalanen rw->value, rw->pc, 0); 187bd8ac686SPekka Paalanen break; 188bd8ac686SPekka Paalanen case MMIO_WRITE: 189a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, 1905e4abc98SSteven Rostedt "W %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 191dee310d0SPekka Paalanen rw->width, secs, usec_rem, rw->map_id, 192dee310d0SPekka Paalanen (unsigned long long)rw->phys, 193736ca61fSPekka Paalanen rw->value, rw->pc, 0); 194bd8ac686SPekka Paalanen break; 195bd8ac686SPekka Paalanen case MMIO_UNKNOWN_OP: 196a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, 1975e4abc98SSteven Rostedt "UNKNOWN %u.%06lu %d 0x%llx %02lx,%02lx," 1985e4abc98SSteven Rostedt "%02lx 0x%lx %d\n", 199dee310d0SPekka Paalanen secs, usec_rem, rw->map_id, 200dee310d0SPekka Paalanen (unsigned long long)rw->phys, 201bd8ac686SPekka Paalanen (rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff, 202736ca61fSPekka Paalanen (rw->value >> 0) & 0xff, rw->pc, 0); 203bd8ac686SPekka Paalanen break; 204bd8ac686SPekka Paalanen default: 205a72e10afSSteven Rostedt (Red Hat) trace_seq_puts(s, "rw what?\n"); 206bd8ac686SPekka Paalanen break; 207bd8ac686SPekka Paalanen } 208a72e10afSSteven Rostedt (Red Hat) 209a72e10afSSteven Rostedt (Red Hat) return trace_handle_return(s); 210bd8ac686SPekka Paalanen } 211bd8ac686SPekka Paalanen 21207f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_map(struct trace_iterator *iter) 213bd8ac686SPekka Paalanen { 214bd8ac686SPekka Paalanen struct trace_entry *entry = iter->ent; 2157104f300SSteven Rostedt struct trace_mmiotrace_map *field; 2167104f300SSteven Rostedt struct mmiotrace_map *m; 217bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 2183928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 219a5dec557SLi Zefan unsigned long usec_rem = do_div(t, USEC_PER_SEC); 220bd8ac686SPekka Paalanen unsigned secs = (unsigned long)t; 221bd8ac686SPekka Paalanen 2227104f300SSteven Rostedt trace_assign_type(field, entry); 2237104f300SSteven Rostedt m = &field->map; 2247104f300SSteven Rostedt 225777e208dSSteven Rostedt switch (m->opcode) { 226bd8ac686SPekka Paalanen case MMIO_PROBE: 227a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, 2285e4abc98SSteven Rostedt "MAP %u.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n", 229dee310d0SPekka Paalanen secs, usec_rem, m->map_id, 230dee310d0SPekka Paalanen (unsigned long long)m->phys, m->virt, m->len, 231e0fd5c2fSPekka Paalanen 0UL, 0); 232bd8ac686SPekka Paalanen break; 233bd8ac686SPekka Paalanen case MMIO_UNPROBE: 234a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, 2355e4abc98SSteven Rostedt "UNMAP %u.%06lu %d 0x%lx %d\n", 236e0fd5c2fSPekka Paalanen secs, usec_rem, m->map_id, 0UL, 0); 237bd8ac686SPekka Paalanen break; 238bd8ac686SPekka Paalanen default: 239a72e10afSSteven Rostedt (Red Hat) trace_seq_puts(s, "map what?\n"); 240bd8ac686SPekka Paalanen break; 241bd8ac686SPekka Paalanen } 242a72e10afSSteven Rostedt (Red Hat) 243a72e10afSSteven Rostedt (Red Hat) return trace_handle_return(s); 244bd8ac686SPekka Paalanen } 245bd8ac686SPekka Paalanen 24607f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_mark(struct trace_iterator *iter) 247fc5e27aeSPekka Paalanen { 248fc5e27aeSPekka Paalanen struct trace_entry *entry = iter->ent; 249777e208dSSteven Rostedt struct print_entry *print = (struct print_entry *)entry; 25048ead020SFrederic Weisbecker const char *msg = print->buf; 251fc5e27aeSPekka Paalanen struct trace_seq *s = &iter->seq; 2523928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 253769b0441SFrederic Weisbecker unsigned long usec_rem = do_div(t, USEC_PER_SEC); 254fc5e27aeSPekka Paalanen unsigned secs = (unsigned long)t; 255fc5e27aeSPekka Paalanen 256fc5e27aeSPekka Paalanen /* The trailing newline must be in the message. */ 257a72e10afSSteven Rostedt (Red Hat) trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg); 258fc5e27aeSPekka Paalanen 259a72e10afSSteven Rostedt (Red Hat) return trace_handle_return(s); 260fc5e27aeSPekka Paalanen } 261fc5e27aeSPekka Paalanen 26207f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_line(struct trace_iterator *iter) 263bd8ac686SPekka Paalanen { 264bd8ac686SPekka Paalanen switch (iter->ent->type) { 265bd8ac686SPekka Paalanen case TRACE_MMIO_RW: 266bd8ac686SPekka Paalanen return mmio_print_rw(iter); 267bd8ac686SPekka Paalanen case TRACE_MMIO_MAP: 268bd8ac686SPekka Paalanen return mmio_print_map(iter); 269fc5e27aeSPekka Paalanen case TRACE_PRINT: 270fc5e27aeSPekka Paalanen return mmio_print_mark(iter); 271bd8ac686SPekka Paalanen default: 27207f4e4f7SFrederic Weisbecker return TRACE_TYPE_HANDLED; /* ignore unknown entries */ 273bd8ac686SPekka Paalanen } 274bd8ac686SPekka Paalanen } 275f984b51eSPekka Paalanen 276f984b51eSPekka Paalanen static struct tracer mmio_tracer __read_mostly = 277f984b51eSPekka Paalanen { 278f984b51eSPekka Paalanen .name = "mmiotrace", 279f984b51eSPekka Paalanen .init = mmio_trace_init, 280f984b51eSPekka Paalanen .reset = mmio_trace_reset, 281bbf5b1a0SSteven Rostedt .start = mmio_trace_start, 282d0a7e8caSPekka Paalanen .pipe_open = mmio_pipe_open, 283d0a7e8caSPekka Paalanen .close = mmio_close, 284d0a7e8caSPekka Paalanen .read = mmio_read, 285bd8ac686SPekka Paalanen .print_line = mmio_print_line, 286c7b3ae0bSZiqian SUN (Zamir) .noboot = true, 287f984b51eSPekka Paalanen }; 288f984b51eSPekka Paalanen 289f984b51eSPekka Paalanen __init static int init_mmio_trace(void) 290f984b51eSPekka Paalanen { 291f984b51eSPekka Paalanen return register_tracer(&mmio_tracer); 292f984b51eSPekka Paalanen } 293f984b51eSPekka Paalanen device_initcall(init_mmio_trace); 294f984b51eSPekka Paalanen 29545dcd8b8SPekka Paalanen static void __trace_mmiotrace_rw(struct trace_array *tr, 29645dcd8b8SPekka Paalanen struct trace_array_cpu *data, 29745dcd8b8SPekka Paalanen struct mmiotrace_rw *rw) 29845dcd8b8SPekka Paalanen { 2992425bcb9SSteven Rostedt (Red Hat) struct trace_event_call *call = &event_mmiotrace_rw; 300*13292494SSteven Rostedt (VMware) struct trace_buffer *buffer = tr->array_buffer.buffer; 3013928a8a2SSteven Rostedt struct ring_buffer_event *event; 302777e208dSSteven Rostedt struct trace_mmiotrace_rw *entry; 30351a763ddSArnaldo Carvalho de Melo int pc = preempt_count(); 30445dcd8b8SPekka Paalanen 305e77405adSSteven Rostedt event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW, 30651a763ddSArnaldo Carvalho de Melo sizeof(*entry), 0, pc); 307173ed24eSPekka Paalanen if (!event) { 308173ed24eSPekka Paalanen atomic_inc(&dropped_count); 3093928a8a2SSteven Rostedt return; 310173ed24eSPekka Paalanen } 3113928a8a2SSteven Rostedt entry = ring_buffer_event_data(event); 312777e208dSSteven Rostedt entry->rw = *rw; 31360ba7702SSteven Rostedt 314f306cc82STom Zanussi if (!call_filter_check_discard(call, entry, buffer, event)) 315b7f0c959SSteven Rostedt (Red Hat) trace_buffer_unlock_commit(tr, buffer, event, 0, pc); 31645dcd8b8SPekka Paalanen } 31745dcd8b8SPekka Paalanen 318bd8ac686SPekka Paalanen void mmio_trace_rw(struct mmiotrace_rw *rw) 319f984b51eSPekka Paalanen { 320f984b51eSPekka Paalanen struct trace_array *tr = mmio_trace_array; 3211c5eb448SSteven Rostedt (VMware) struct trace_array_cpu *data = per_cpu_ptr(tr->array_buffer.data, smp_processor_id()); 322bd8ac686SPekka Paalanen __trace_mmiotrace_rw(tr, data, rw); 323bd8ac686SPekka Paalanen } 324f984b51eSPekka Paalanen 32545dcd8b8SPekka Paalanen static void __trace_mmiotrace_map(struct trace_array *tr, 32645dcd8b8SPekka Paalanen struct trace_array_cpu *data, 32745dcd8b8SPekka Paalanen struct mmiotrace_map *map) 32845dcd8b8SPekka Paalanen { 3292425bcb9SSteven Rostedt (Red Hat) struct trace_event_call *call = &event_mmiotrace_map; 330*13292494SSteven Rostedt (VMware) struct trace_buffer *buffer = tr->array_buffer.buffer; 3313928a8a2SSteven Rostedt struct ring_buffer_event *event; 332777e208dSSteven Rostedt struct trace_mmiotrace_map *entry; 33351a763ddSArnaldo Carvalho de Melo int pc = preempt_count(); 33445dcd8b8SPekka Paalanen 335e77405adSSteven Rostedt event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP, 33651a763ddSArnaldo Carvalho de Melo sizeof(*entry), 0, pc); 337173ed24eSPekka Paalanen if (!event) { 338173ed24eSPekka Paalanen atomic_inc(&dropped_count); 3393928a8a2SSteven Rostedt return; 340173ed24eSPekka Paalanen } 3413928a8a2SSteven Rostedt entry = ring_buffer_event_data(event); 342777e208dSSteven Rostedt entry->map = *map; 34360ba7702SSteven Rostedt 344f306cc82STom Zanussi if (!call_filter_check_discard(call, entry, buffer, event)) 345b7f0c959SSteven Rostedt (Red Hat) trace_buffer_unlock_commit(tr, buffer, event, 0, pc); 34645dcd8b8SPekka Paalanen } 34745dcd8b8SPekka Paalanen 348bd8ac686SPekka Paalanen void mmio_trace_mapping(struct mmiotrace_map *map) 349bd8ac686SPekka Paalanen { 350bd8ac686SPekka Paalanen struct trace_array *tr = mmio_trace_array; 351bd8ac686SPekka Paalanen struct trace_array_cpu *data; 352bd8ac686SPekka Paalanen 353bd8ac686SPekka Paalanen preempt_disable(); 3541c5eb448SSteven Rostedt (VMware) data = per_cpu_ptr(tr->array_buffer.data, smp_processor_id()); 355bd8ac686SPekka Paalanen __trace_mmiotrace_map(tr, data, map); 356bd8ac686SPekka Paalanen preempt_enable(); 357f984b51eSPekka Paalanen } 3589e57fb35SPekka Paalanen 3599e57fb35SPekka Paalanen int mmio_trace_printk(const char *fmt, va_list args) 3609e57fb35SPekka Paalanen { 36140ce74f1SSteven Rostedt return trace_vprintk(0, fmt, args); 3629e57fb35SPekka Paalanen } 363