1f984b51eSPekka Paalanen /* 2f984b51eSPekka Paalanen * Memory mapped I/O tracing 3f984b51eSPekka Paalanen * 4f984b51eSPekka Paalanen * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi> 5f984b51eSPekka Paalanen */ 6f984b51eSPekka Paalanen 7f984b51eSPekka Paalanen #define DEBUG 1 8f984b51eSPekka Paalanen 9f984b51eSPekka Paalanen #include <linux/kernel.h> 10f984b51eSPekka Paalanen #include <linux/mmiotrace.h> 1113829537SPekka Paalanen #include <linux/pci.h> 12f984b51eSPekka Paalanen 13f984b51eSPekka Paalanen #include "trace.h" 14f984b51eSPekka Paalanen 15d0a7e8caSPekka Paalanen struct header_iter { 16d0a7e8caSPekka Paalanen struct pci_dev *dev; 17d0a7e8caSPekka Paalanen }; 18d0a7e8caSPekka Paalanen 19f984b51eSPekka Paalanen static struct trace_array *mmio_trace_array; 202039238bSPekka Paalanen static bool overrun_detected; 21*7ee1768dSPekka Paalanen static unsigned long prev_overruns; 22f984b51eSPekka Paalanen 23bd8ac686SPekka Paalanen static void mmio_reset_data(struct trace_array *tr) 24bd8ac686SPekka Paalanen { 25bd8ac686SPekka Paalanen int cpu; 26bd8ac686SPekka Paalanen 272039238bSPekka Paalanen overrun_detected = false; 28*7ee1768dSPekka Paalanen prev_overruns = 0; 29bd8ac686SPekka Paalanen tr->time_start = ftrace_now(tr->cpu); 30bd8ac686SPekka Paalanen 31bd8ac686SPekka Paalanen for_each_online_cpu(cpu) 323928a8a2SSteven Rostedt tracing_reset(tr, cpu); 33bd8ac686SPekka Paalanen } 34f984b51eSPekka Paalanen 35f984b51eSPekka Paalanen static void mmio_trace_init(struct trace_array *tr) 36f984b51eSPekka Paalanen { 37f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 38f984b51eSPekka Paalanen mmio_trace_array = tr; 39bd8ac686SPekka Paalanen if (tr->ctrl) { 40bd8ac686SPekka Paalanen mmio_reset_data(tr); 41f984b51eSPekka Paalanen enable_mmiotrace(); 42f984b51eSPekka Paalanen } 43bd8ac686SPekka Paalanen } 44f984b51eSPekka Paalanen 45f984b51eSPekka Paalanen static void mmio_trace_reset(struct trace_array *tr) 46f984b51eSPekka Paalanen { 47f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 48f984b51eSPekka Paalanen if (tr->ctrl) 49f984b51eSPekka Paalanen disable_mmiotrace(); 50bd8ac686SPekka Paalanen mmio_reset_data(tr); 51bd8ac686SPekka Paalanen mmio_trace_array = NULL; 52f984b51eSPekka Paalanen } 53f984b51eSPekka Paalanen 54f984b51eSPekka Paalanen static void mmio_trace_ctrl_update(struct trace_array *tr) 55f984b51eSPekka Paalanen { 56f984b51eSPekka Paalanen pr_debug("in %s\n", __func__); 57bd8ac686SPekka Paalanen if (tr->ctrl) { 58bd8ac686SPekka Paalanen mmio_reset_data(tr); 59f984b51eSPekka Paalanen enable_mmiotrace(); 60bd8ac686SPekka Paalanen } else { 61f984b51eSPekka Paalanen disable_mmiotrace(); 62f984b51eSPekka Paalanen } 63bd8ac686SPekka Paalanen } 64bd8ac686SPekka Paalanen 6513829537SPekka Paalanen static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) 6613829537SPekka Paalanen { 6713829537SPekka Paalanen int ret = 0; 6813829537SPekka Paalanen int i; 6913829537SPekka Paalanen resource_size_t start, end; 7013829537SPekka Paalanen const struct pci_driver *drv = pci_dev_driver(dev); 7113829537SPekka Paalanen 7213829537SPekka Paalanen /* XXX: incomplete checks for trace_seq_printf() return value */ 7313829537SPekka Paalanen ret += trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x", 7413829537SPekka Paalanen dev->bus->number, dev->devfn, 7513829537SPekka Paalanen dev->vendor, dev->device, dev->irq); 7613829537SPekka Paalanen /* 7713829537SPekka Paalanen * XXX: is pci_resource_to_user() appropriate, since we are 7813829537SPekka Paalanen * supposed to interpret the __ioremap() phys_addr argument based on 7913829537SPekka Paalanen * these printed values? 8013829537SPekka Paalanen */ 8113829537SPekka Paalanen for (i = 0; i < 7; i++) { 8213829537SPekka Paalanen pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); 8313829537SPekka Paalanen ret += trace_seq_printf(s, " %llx", 8413829537SPekka Paalanen (unsigned long long)(start | 8513829537SPekka Paalanen (dev->resource[i].flags & PCI_REGION_FLAG_MASK))); 8613829537SPekka Paalanen } 8713829537SPekka Paalanen for (i = 0; i < 7; i++) { 8813829537SPekka Paalanen pci_resource_to_user(dev, i, &dev->resource[i], &start, &end); 8913829537SPekka Paalanen ret += trace_seq_printf(s, " %llx", 9013829537SPekka Paalanen dev->resource[i].start < dev->resource[i].end ? 9113829537SPekka Paalanen (unsigned long long)(end - start) + 1 : 0); 9213829537SPekka Paalanen } 9313829537SPekka Paalanen if (drv) 9413829537SPekka Paalanen ret += trace_seq_printf(s, " %s\n", drv->name); 9513829537SPekka Paalanen else 9613829537SPekka Paalanen ret += trace_seq_printf(s, " \n"); 9713829537SPekka Paalanen return ret; 9813829537SPekka Paalanen } 9913829537SPekka Paalanen 100d0a7e8caSPekka Paalanen static void destroy_header_iter(struct header_iter *hiter) 101bd8ac686SPekka Paalanen { 102d0a7e8caSPekka Paalanen if (!hiter) 103d0a7e8caSPekka Paalanen return; 104d0a7e8caSPekka Paalanen pci_dev_put(hiter->dev); 105d0a7e8caSPekka Paalanen kfree(hiter); 106d0a7e8caSPekka Paalanen } 107d0a7e8caSPekka Paalanen 108d0a7e8caSPekka Paalanen static void mmio_pipe_open(struct trace_iterator *iter) 109d0a7e8caSPekka Paalanen { 110d0a7e8caSPekka Paalanen struct header_iter *hiter; 111bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 11213829537SPekka Paalanen 11313829537SPekka Paalanen trace_seq_printf(s, "VERSION 20070824\n"); 11413829537SPekka Paalanen 115d0a7e8caSPekka Paalanen hiter = kzalloc(sizeof(*hiter), GFP_KERNEL); 116d0a7e8caSPekka Paalanen if (!hiter) 117d0a7e8caSPekka Paalanen return; 118d0a7e8caSPekka Paalanen 119d0a7e8caSPekka Paalanen hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 120d0a7e8caSPekka Paalanen iter->private = hiter; 121d0a7e8caSPekka Paalanen } 122d0a7e8caSPekka Paalanen 123d0a7e8caSPekka Paalanen /* XXX: This is not called when the pipe is closed! */ 124d0a7e8caSPekka Paalanen static void mmio_close(struct trace_iterator *iter) 125d0a7e8caSPekka Paalanen { 126d0a7e8caSPekka Paalanen struct header_iter *hiter = iter->private; 127d0a7e8caSPekka Paalanen destroy_header_iter(hiter); 128d0a7e8caSPekka Paalanen iter->private = NULL; 129d0a7e8caSPekka Paalanen } 130d0a7e8caSPekka Paalanen 1312039238bSPekka Paalanen static unsigned long count_overruns(struct trace_iterator *iter) 1322039238bSPekka Paalanen { 1332039238bSPekka Paalanen unsigned long cnt = 0; 134*7ee1768dSPekka Paalanen unsigned long over = ring_buffer_overruns(iter->tr->buffer); 135*7ee1768dSPekka Paalanen 136*7ee1768dSPekka Paalanen if (over > prev_overruns) 137*7ee1768dSPekka Paalanen cnt = over - prev_overruns; 138*7ee1768dSPekka Paalanen prev_overruns = over; 1392039238bSPekka Paalanen return cnt; 1402039238bSPekka Paalanen } 1412039238bSPekka Paalanen 142d0a7e8caSPekka Paalanen static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, 143d0a7e8caSPekka Paalanen char __user *ubuf, size_t cnt, loff_t *ppos) 144d0a7e8caSPekka Paalanen { 145d0a7e8caSPekka Paalanen ssize_t ret; 146d0a7e8caSPekka Paalanen struct header_iter *hiter = iter->private; 147d0a7e8caSPekka Paalanen struct trace_seq *s = &iter->seq; 1482039238bSPekka Paalanen unsigned long n; 1492039238bSPekka Paalanen 1502039238bSPekka Paalanen n = count_overruns(iter); 1512039238bSPekka Paalanen if (n) { 1522039238bSPekka Paalanen /* XXX: This is later than where events were lost. */ 1532039238bSPekka Paalanen trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n); 1542039238bSPekka Paalanen if (!overrun_detected) 1552039238bSPekka Paalanen pr_warning("mmiotrace has lost events.\n"); 1562039238bSPekka Paalanen overrun_detected = true; 1572039238bSPekka Paalanen goto print_out; 1582039238bSPekka Paalanen } 159d0a7e8caSPekka Paalanen 160d0a7e8caSPekka Paalanen if (!hiter) 161d0a7e8caSPekka Paalanen return 0; 162d0a7e8caSPekka Paalanen 163d0a7e8caSPekka Paalanen mmio_print_pcidev(s, hiter->dev); 164d0a7e8caSPekka Paalanen hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev); 165d0a7e8caSPekka Paalanen 166d0a7e8caSPekka Paalanen if (!hiter->dev) { 167d0a7e8caSPekka Paalanen destroy_header_iter(hiter); 168d0a7e8caSPekka Paalanen iter->private = NULL; 169d0a7e8caSPekka Paalanen } 170d0a7e8caSPekka Paalanen 1712039238bSPekka Paalanen print_out: 172d0a7e8caSPekka Paalanen ret = trace_seq_to_user(s, ubuf, cnt); 173d0a7e8caSPekka Paalanen return (ret == -EBUSY) ? 0 : ret; 174bd8ac686SPekka Paalanen } 175bd8ac686SPekka Paalanen 17607f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_rw(struct trace_iterator *iter) 177bd8ac686SPekka Paalanen { 178bd8ac686SPekka Paalanen struct trace_entry *entry = iter->ent; 1797104f300SSteven Rostedt struct trace_mmiotrace_rw *field; 1807104f300SSteven Rostedt struct mmiotrace_rw *rw; 181bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 1823928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 183bd8ac686SPekka Paalanen unsigned long usec_rem = do_div(t, 1000000ULL); 184bd8ac686SPekka Paalanen unsigned secs = (unsigned long)t; 185bd8ac686SPekka Paalanen int ret = 1; 186bd8ac686SPekka Paalanen 1877104f300SSteven Rostedt trace_assign_type(field, entry); 1887104f300SSteven Rostedt rw = &field->rw; 1897104f300SSteven Rostedt 190777e208dSSteven Rostedt switch (rw->opcode) { 191bd8ac686SPekka Paalanen case MMIO_READ: 192bd8ac686SPekka Paalanen ret = trace_seq_printf(s, 193dee310d0SPekka Paalanen "R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 194dee310d0SPekka Paalanen rw->width, secs, usec_rem, rw->map_id, 195dee310d0SPekka Paalanen (unsigned long long)rw->phys, 196736ca61fSPekka Paalanen rw->value, rw->pc, 0); 197bd8ac686SPekka Paalanen break; 198bd8ac686SPekka Paalanen case MMIO_WRITE: 199bd8ac686SPekka Paalanen ret = trace_seq_printf(s, 200dee310d0SPekka Paalanen "W %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", 201dee310d0SPekka Paalanen rw->width, secs, usec_rem, rw->map_id, 202dee310d0SPekka Paalanen (unsigned long long)rw->phys, 203736ca61fSPekka Paalanen rw->value, rw->pc, 0); 204bd8ac686SPekka Paalanen break; 205bd8ac686SPekka Paalanen case MMIO_UNKNOWN_OP: 206bd8ac686SPekka Paalanen ret = trace_seq_printf(s, 207dee310d0SPekka Paalanen "UNKNOWN %lu.%06lu %d 0x%llx %02x,%02x,%02x 0x%lx %d\n", 208dee310d0SPekka Paalanen secs, usec_rem, rw->map_id, 209dee310d0SPekka Paalanen (unsigned long long)rw->phys, 210bd8ac686SPekka Paalanen (rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff, 211736ca61fSPekka Paalanen (rw->value >> 0) & 0xff, rw->pc, 0); 212bd8ac686SPekka Paalanen break; 213bd8ac686SPekka Paalanen default: 214bd8ac686SPekka Paalanen ret = trace_seq_printf(s, "rw what?\n"); 215bd8ac686SPekka Paalanen break; 216bd8ac686SPekka Paalanen } 217bd8ac686SPekka Paalanen if (ret) 21807f4e4f7SFrederic Weisbecker return TRACE_TYPE_HANDLED; 21907f4e4f7SFrederic Weisbecker return TRACE_TYPE_PARTIAL_LINE; 220bd8ac686SPekka Paalanen } 221bd8ac686SPekka Paalanen 22207f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_map(struct trace_iterator *iter) 223bd8ac686SPekka Paalanen { 224bd8ac686SPekka Paalanen struct trace_entry *entry = iter->ent; 2257104f300SSteven Rostedt struct trace_mmiotrace_map *field; 2267104f300SSteven Rostedt struct mmiotrace_map *m; 227bd8ac686SPekka Paalanen struct trace_seq *s = &iter->seq; 2283928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 229bd8ac686SPekka Paalanen unsigned long usec_rem = do_div(t, 1000000ULL); 230bd8ac686SPekka Paalanen unsigned secs = (unsigned long)t; 23107f4e4f7SFrederic Weisbecker int ret; 232bd8ac686SPekka Paalanen 2337104f300SSteven Rostedt trace_assign_type(field, entry); 2347104f300SSteven Rostedt m = &field->map; 2357104f300SSteven Rostedt 236777e208dSSteven Rostedt switch (m->opcode) { 237bd8ac686SPekka Paalanen case MMIO_PROBE: 238bd8ac686SPekka Paalanen ret = trace_seq_printf(s, 239dee310d0SPekka Paalanen "MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n", 240dee310d0SPekka Paalanen secs, usec_rem, m->map_id, 241dee310d0SPekka Paalanen (unsigned long long)m->phys, m->virt, m->len, 242e0fd5c2fSPekka Paalanen 0UL, 0); 243bd8ac686SPekka Paalanen break; 244bd8ac686SPekka Paalanen case MMIO_UNPROBE: 245bd8ac686SPekka Paalanen ret = trace_seq_printf(s, 246bd8ac686SPekka Paalanen "UNMAP %lu.%06lu %d 0x%lx %d\n", 247e0fd5c2fSPekka Paalanen secs, usec_rem, m->map_id, 0UL, 0); 248bd8ac686SPekka Paalanen break; 249bd8ac686SPekka Paalanen default: 250bd8ac686SPekka Paalanen ret = trace_seq_printf(s, "map what?\n"); 251bd8ac686SPekka Paalanen break; 252bd8ac686SPekka Paalanen } 253bd8ac686SPekka Paalanen if (ret) 25407f4e4f7SFrederic Weisbecker return TRACE_TYPE_HANDLED; 25507f4e4f7SFrederic Weisbecker return TRACE_TYPE_PARTIAL_LINE; 256bd8ac686SPekka Paalanen } 257bd8ac686SPekka Paalanen 25807f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_mark(struct trace_iterator *iter) 259fc5e27aeSPekka Paalanen { 260fc5e27aeSPekka Paalanen struct trace_entry *entry = iter->ent; 261777e208dSSteven Rostedt struct print_entry *print = (struct print_entry *)entry; 262777e208dSSteven Rostedt const char *msg = print->buf; 263fc5e27aeSPekka Paalanen struct trace_seq *s = &iter->seq; 2643928a8a2SSteven Rostedt unsigned long long t = ns2usecs(iter->ts); 265fc5e27aeSPekka Paalanen unsigned long usec_rem = do_div(t, 1000000ULL); 266fc5e27aeSPekka Paalanen unsigned secs = (unsigned long)t; 267fc5e27aeSPekka Paalanen int ret; 268fc5e27aeSPekka Paalanen 269fc5e27aeSPekka Paalanen /* The trailing newline must be in the message. */ 270fc5e27aeSPekka Paalanen ret = trace_seq_printf(s, "MARK %lu.%06lu %s", secs, usec_rem, msg); 271fc5e27aeSPekka Paalanen if (!ret) 27207f4e4f7SFrederic Weisbecker return TRACE_TYPE_PARTIAL_LINE; 273fc5e27aeSPekka Paalanen 274777e208dSSteven Rostedt if (entry->flags & TRACE_FLAG_CONT) 275fc5e27aeSPekka Paalanen trace_seq_print_cont(s, iter); 276fc5e27aeSPekka Paalanen 27707f4e4f7SFrederic Weisbecker return TRACE_TYPE_HANDLED; 278fc5e27aeSPekka Paalanen } 279fc5e27aeSPekka Paalanen 28007f4e4f7SFrederic Weisbecker static enum print_line_t mmio_print_line(struct trace_iterator *iter) 281bd8ac686SPekka Paalanen { 282bd8ac686SPekka Paalanen switch (iter->ent->type) { 283bd8ac686SPekka Paalanen case TRACE_MMIO_RW: 284bd8ac686SPekka Paalanen return mmio_print_rw(iter); 285bd8ac686SPekka Paalanen case TRACE_MMIO_MAP: 286bd8ac686SPekka Paalanen return mmio_print_map(iter); 287fc5e27aeSPekka Paalanen case TRACE_PRINT: 288fc5e27aeSPekka Paalanen return mmio_print_mark(iter); 289bd8ac686SPekka Paalanen default: 29007f4e4f7SFrederic Weisbecker return TRACE_TYPE_HANDLED; /* ignore unknown entries */ 291bd8ac686SPekka Paalanen } 292bd8ac686SPekka Paalanen } 293f984b51eSPekka Paalanen 294f984b51eSPekka Paalanen static struct tracer mmio_tracer __read_mostly = 295f984b51eSPekka Paalanen { 296f984b51eSPekka Paalanen .name = "mmiotrace", 297f984b51eSPekka Paalanen .init = mmio_trace_init, 298f984b51eSPekka Paalanen .reset = mmio_trace_reset, 299d0a7e8caSPekka Paalanen .pipe_open = mmio_pipe_open, 300d0a7e8caSPekka Paalanen .close = mmio_close, 301d0a7e8caSPekka Paalanen .read = mmio_read, 302f984b51eSPekka Paalanen .ctrl_update = mmio_trace_ctrl_update, 303bd8ac686SPekka Paalanen .print_line = mmio_print_line, 304f984b51eSPekka Paalanen }; 305f984b51eSPekka Paalanen 306f984b51eSPekka Paalanen __init static int init_mmio_trace(void) 307f984b51eSPekka Paalanen { 308f984b51eSPekka Paalanen return register_tracer(&mmio_tracer); 309f984b51eSPekka Paalanen } 310f984b51eSPekka Paalanen device_initcall(init_mmio_trace); 311f984b51eSPekka Paalanen 31245dcd8b8SPekka Paalanen static void __trace_mmiotrace_rw(struct trace_array *tr, 31345dcd8b8SPekka Paalanen struct trace_array_cpu *data, 31445dcd8b8SPekka Paalanen struct mmiotrace_rw *rw) 31545dcd8b8SPekka Paalanen { 3163928a8a2SSteven Rostedt struct ring_buffer_event *event; 317777e208dSSteven Rostedt struct trace_mmiotrace_rw *entry; 31845dcd8b8SPekka Paalanen unsigned long irq_flags; 31945dcd8b8SPekka Paalanen 3203928a8a2SSteven Rostedt event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), 3213928a8a2SSteven Rostedt &irq_flags); 3223928a8a2SSteven Rostedt if (!event) 3233928a8a2SSteven Rostedt return; 3243928a8a2SSteven Rostedt entry = ring_buffer_event_data(event); 32538697053SSteven Rostedt tracing_generic_entry_update(&entry->ent, 0, preempt_count()); 326777e208dSSteven Rostedt entry->ent.type = TRACE_MMIO_RW; 327777e208dSSteven Rostedt entry->rw = *rw; 3283928a8a2SSteven Rostedt ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 32945dcd8b8SPekka Paalanen 33045dcd8b8SPekka Paalanen trace_wake_up(); 33145dcd8b8SPekka Paalanen } 33245dcd8b8SPekka Paalanen 333bd8ac686SPekka Paalanen void mmio_trace_rw(struct mmiotrace_rw *rw) 334f984b51eSPekka Paalanen { 335f984b51eSPekka Paalanen struct trace_array *tr = mmio_trace_array; 336f984b51eSPekka Paalanen struct trace_array_cpu *data = tr->data[smp_processor_id()]; 337bd8ac686SPekka Paalanen __trace_mmiotrace_rw(tr, data, rw); 338bd8ac686SPekka Paalanen } 339f984b51eSPekka Paalanen 34045dcd8b8SPekka Paalanen static void __trace_mmiotrace_map(struct trace_array *tr, 34145dcd8b8SPekka Paalanen struct trace_array_cpu *data, 34245dcd8b8SPekka Paalanen struct mmiotrace_map *map) 34345dcd8b8SPekka Paalanen { 3443928a8a2SSteven Rostedt struct ring_buffer_event *event; 345777e208dSSteven Rostedt struct trace_mmiotrace_map *entry; 34645dcd8b8SPekka Paalanen unsigned long irq_flags; 34745dcd8b8SPekka Paalanen 3483928a8a2SSteven Rostedt event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), 3493928a8a2SSteven Rostedt &irq_flags); 3503928a8a2SSteven Rostedt if (!event) 3513928a8a2SSteven Rostedt return; 3523928a8a2SSteven Rostedt entry = ring_buffer_event_data(event); 35338697053SSteven Rostedt tracing_generic_entry_update(&entry->ent, 0, preempt_count()); 354777e208dSSteven Rostedt entry->ent.type = TRACE_MMIO_MAP; 355777e208dSSteven Rostedt entry->map = *map; 3563928a8a2SSteven Rostedt ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 35745dcd8b8SPekka Paalanen 35845dcd8b8SPekka Paalanen trace_wake_up(); 35945dcd8b8SPekka Paalanen } 36045dcd8b8SPekka Paalanen 361bd8ac686SPekka Paalanen void mmio_trace_mapping(struct mmiotrace_map *map) 362bd8ac686SPekka Paalanen { 363bd8ac686SPekka Paalanen struct trace_array *tr = mmio_trace_array; 364bd8ac686SPekka Paalanen struct trace_array_cpu *data; 365bd8ac686SPekka Paalanen 366bd8ac686SPekka Paalanen preempt_disable(); 367bd8ac686SPekka Paalanen data = tr->data[smp_processor_id()]; 368bd8ac686SPekka Paalanen __trace_mmiotrace_map(tr, data, map); 369bd8ac686SPekka Paalanen preempt_enable(); 370f984b51eSPekka Paalanen } 3719e57fb35SPekka Paalanen 3729e57fb35SPekka Paalanen int mmio_trace_printk(const char *fmt, va_list args) 3739e57fb35SPekka Paalanen { 3749e57fb35SPekka Paalanen return trace_vprintk(0, fmt, args); 3759e57fb35SPekka Paalanen } 376