Linux Audio

Check our new training course

Loading...
v3.15
  1/*
  2 * Memory mapped I/O tracing
  3 *
  4 * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi>
  5 */
  6
  7#define DEBUG 1
  8
  9#include <linux/kernel.h>
 10#include <linux/mmiotrace.h>
 11#include <linux/pci.h>
 12#include <linux/slab.h>
 13#include <linux/time.h>
 14
 15#include <linux/atomic.h>
 16
 17#include "trace.h"
 18#include "trace_output.h"
 19
 20struct header_iter {
 21	struct pci_dev *dev;
 22};
 23
 24static struct trace_array *mmio_trace_array;
 25static bool overrun_detected;
 26static unsigned long prev_overruns;
 27static atomic_t dropped_count;
 28
 29static void mmio_reset_data(struct trace_array *tr)
 30{
 31	overrun_detected = false;
 32	prev_overruns = 0;
 33
 34	tracing_reset_online_cpus(&tr->trace_buffer);
 35}
 36
 37static int mmio_trace_init(struct trace_array *tr)
 38{
 39	pr_debug("in %s\n", __func__);
 40	mmio_trace_array = tr;
 41
 42	mmio_reset_data(tr);
 43	enable_mmiotrace();
 44	return 0;
 45}
 46
 47static void mmio_trace_reset(struct trace_array *tr)
 48{
 49	pr_debug("in %s\n", __func__);
 50
 51	disable_mmiotrace();
 52	mmio_reset_data(tr);
 53	mmio_trace_array = NULL;
 54}
 55
 56static void mmio_trace_start(struct trace_array *tr)
 57{
 58	pr_debug("in %s\n", __func__);
 59	mmio_reset_data(tr);
 60}
 61
 62static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
 63{
 64	int ret = 0;
 65	int i;
 66	resource_size_t start, end;
 67	const struct pci_driver *drv = pci_dev_driver(dev);
 68
 69	/* XXX: incomplete checks for trace_seq_printf() return value */
 70	ret += trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
 71				dev->bus->number, dev->devfn,
 72				dev->vendor, dev->device, dev->irq);
 73	/*
 74	 * XXX: is pci_resource_to_user() appropriate, since we are
 75	 * supposed to interpret the __ioremap() phys_addr argument based on
 76	 * these printed values?
 77	 */
 78	for (i = 0; i < 7; i++) {
 79		pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
 80		ret += trace_seq_printf(s, " %llx",
 81			(unsigned long long)(start |
 82			(dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
 83	}
 84	for (i = 0; i < 7; i++) {
 85		pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
 86		ret += trace_seq_printf(s, " %llx",
 87			dev->resource[i].start < dev->resource[i].end ?
 88			(unsigned long long)(end - start) + 1 : 0);
 89	}
 90	if (drv)
 91		ret += trace_seq_printf(s, " %s\n", drv->name);
 92	else
 93		ret += trace_seq_puts(s, " \n");
 94	return ret;
 95}
 96
 97static void destroy_header_iter(struct header_iter *hiter)
 98{
 99	if (!hiter)
100		return;
101	pci_dev_put(hiter->dev);
102	kfree(hiter);
103}
104
105static void mmio_pipe_open(struct trace_iterator *iter)
106{
107	struct header_iter *hiter;
108	struct trace_seq *s = &iter->seq;
109
110	trace_seq_puts(s, "VERSION 20070824\n");
111
112	hiter = kzalloc(sizeof(*hiter), GFP_KERNEL);
113	if (!hiter)
114		return;
115
116	hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
117	iter->private = hiter;
118}
119
120/* XXX: This is not called when the pipe is closed! */
121static void mmio_close(struct trace_iterator *iter)
122{
123	struct header_iter *hiter = iter->private;
124	destroy_header_iter(hiter);
125	iter->private = NULL;
126}
127
128static unsigned long count_overruns(struct trace_iterator *iter)
129{
130	unsigned long cnt = atomic_xchg(&dropped_count, 0);
131	unsigned long over = ring_buffer_overruns(iter->trace_buffer->buffer);
132
133	if (over > prev_overruns)
134		cnt += over - prev_overruns;
135	prev_overruns = over;
136	return cnt;
137}
138
139static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp,
140				char __user *ubuf, size_t cnt, loff_t *ppos)
141{
142	ssize_t ret;
143	struct header_iter *hiter = iter->private;
144	struct trace_seq *s = &iter->seq;
145	unsigned long n;
146
147	n = count_overruns(iter);
148	if (n) {
149		/* XXX: This is later than where events were lost. */
150		trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n);
151		if (!overrun_detected)
152			pr_warning("mmiotrace has lost events.\n");
153		overrun_detected = true;
154		goto print_out;
155	}
156
157	if (!hiter)
158		return 0;
159
160	mmio_print_pcidev(s, hiter->dev);
161	hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev);
162
163	if (!hiter->dev) {
164		destroy_header_iter(hiter);
165		iter->private = NULL;
166	}
167
168print_out:
169	ret = trace_seq_to_user(s, ubuf, cnt);
170	return (ret == -EBUSY) ? 0 : ret;
171}
172
173static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
174{
175	struct trace_entry *entry = iter->ent;
176	struct trace_mmiotrace_rw *field;
177	struct mmiotrace_rw *rw;
178	struct trace_seq *s	= &iter->seq;
179	unsigned long long t	= ns2usecs(iter->ts);
180	unsigned long usec_rem	= do_div(t, USEC_PER_SEC);
181	unsigned secs		= (unsigned long)t;
182	int ret = 1;
183
184	trace_assign_type(field, entry);
185	rw = &field->rw;
186
187	switch (rw->opcode) {
188	case MMIO_READ:
189		ret = trace_seq_printf(s,
190			"R %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
191			rw->width, secs, usec_rem, rw->map_id,
192			(unsigned long long)rw->phys,
193			rw->value, rw->pc, 0);
194		break;
195	case MMIO_WRITE:
196		ret = trace_seq_printf(s,
197			"W %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
198			rw->width, secs, usec_rem, rw->map_id,
199			(unsigned long long)rw->phys,
200			rw->value, rw->pc, 0);
201		break;
202	case MMIO_UNKNOWN_OP:
203		ret = trace_seq_printf(s,
204			"UNKNOWN %u.%06lu %d 0x%llx %02lx,%02lx,"
205			"%02lx 0x%lx %d\n",
206			secs, usec_rem, rw->map_id,
207			(unsigned long long)rw->phys,
208			(rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff,
209			(rw->value >> 0) & 0xff, rw->pc, 0);
210		break;
211	default:
212		ret = trace_seq_puts(s, "rw what?\n");
213		break;
214	}
215	if (ret)
216		return TRACE_TYPE_HANDLED;
217	return TRACE_TYPE_PARTIAL_LINE;
218}
219
220static enum print_line_t mmio_print_map(struct trace_iterator *iter)
221{
222	struct trace_entry *entry = iter->ent;
223	struct trace_mmiotrace_map *field;
224	struct mmiotrace_map *m;
225	struct trace_seq *s	= &iter->seq;
226	unsigned long long t	= ns2usecs(iter->ts);
227	unsigned long usec_rem	= do_div(t, USEC_PER_SEC);
228	unsigned secs		= (unsigned long)t;
229	int ret;
230
231	trace_assign_type(field, entry);
232	m = &field->map;
233
234	switch (m->opcode) {
235	case MMIO_PROBE:
236		ret = trace_seq_printf(s,
237			"MAP %u.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
238			secs, usec_rem, m->map_id,
239			(unsigned long long)m->phys, m->virt, m->len,
240			0UL, 0);
241		break;
242	case MMIO_UNPROBE:
243		ret = trace_seq_printf(s,
244			"UNMAP %u.%06lu %d 0x%lx %d\n",
245			secs, usec_rem, m->map_id, 0UL, 0);
246		break;
247	default:
248		ret = trace_seq_puts(s, "map what?\n");
249		break;
250	}
251	if (ret)
252		return TRACE_TYPE_HANDLED;
253	return TRACE_TYPE_PARTIAL_LINE;
254}
255
256static enum print_line_t mmio_print_mark(struct trace_iterator *iter)
257{
258	struct trace_entry *entry = iter->ent;
259	struct print_entry *print = (struct print_entry *)entry;
260	const char *msg		= print->buf;
261	struct trace_seq *s	= &iter->seq;
262	unsigned long long t	= ns2usecs(iter->ts);
263	unsigned long usec_rem	= do_div(t, USEC_PER_SEC);
264	unsigned secs		= (unsigned long)t;
265	int ret;
266
267	/* The trailing newline must be in the message. */
268	ret = trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg);
269	if (!ret)
270		return TRACE_TYPE_PARTIAL_LINE;
271
272	return TRACE_TYPE_HANDLED;
273}
274
275static enum print_line_t mmio_print_line(struct trace_iterator *iter)
276{
277	switch (iter->ent->type) {
278	case TRACE_MMIO_RW:
279		return mmio_print_rw(iter);
280	case TRACE_MMIO_MAP:
281		return mmio_print_map(iter);
282	case TRACE_PRINT:
283		return mmio_print_mark(iter);
284	default:
285		return TRACE_TYPE_HANDLED; /* ignore unknown entries */
286	}
287}
288
289static struct tracer mmio_tracer __read_mostly =
290{
291	.name		= "mmiotrace",
292	.init		= mmio_trace_init,
293	.reset		= mmio_trace_reset,
294	.start		= mmio_trace_start,
295	.pipe_open	= mmio_pipe_open,
296	.close		= mmio_close,
297	.read		= mmio_read,
298	.print_line	= mmio_print_line,
299};
300
301__init static int init_mmio_trace(void)
302{
303	return register_tracer(&mmio_tracer);
304}
305device_initcall(init_mmio_trace);
306
307static void __trace_mmiotrace_rw(struct trace_array *tr,
308				struct trace_array_cpu *data,
309				struct mmiotrace_rw *rw)
310{
311	struct ftrace_event_call *call = &event_mmiotrace_rw;
312	struct ring_buffer *buffer = tr->trace_buffer.buffer;
313	struct ring_buffer_event *event;
314	struct trace_mmiotrace_rw *entry;
315	int pc = preempt_count();
316
317	event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW,
318					  sizeof(*entry), 0, pc);
319	if (!event) {
320		atomic_inc(&dropped_count);
321		return;
322	}
323	entry	= ring_buffer_event_data(event);
324	entry->rw			= *rw;
325
326	if (!call_filter_check_discard(call, entry, buffer, event))
327		trace_buffer_unlock_commit(buffer, event, 0, pc);
328}
329
330void mmio_trace_rw(struct mmiotrace_rw *rw)
331{
332	struct trace_array *tr = mmio_trace_array;
333	struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
334	__trace_mmiotrace_rw(tr, data, rw);
335}
336
337static void __trace_mmiotrace_map(struct trace_array *tr,
338				struct trace_array_cpu *data,
339				struct mmiotrace_map *map)
340{
341	struct ftrace_event_call *call = &event_mmiotrace_map;
342	struct ring_buffer *buffer = tr->trace_buffer.buffer;
343	struct ring_buffer_event *event;
344	struct trace_mmiotrace_map *entry;
345	int pc = preempt_count();
346
347	event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP,
348					  sizeof(*entry), 0, pc);
349	if (!event) {
350		atomic_inc(&dropped_count);
351		return;
352	}
353	entry	= ring_buffer_event_data(event);
354	entry->map			= *map;
355
356	if (!call_filter_check_discard(call, entry, buffer, event))
357		trace_buffer_unlock_commit(buffer, event, 0, pc);
358}
359
360void mmio_trace_mapping(struct mmiotrace_map *map)
361{
362	struct trace_array *tr = mmio_trace_array;
363	struct trace_array_cpu *data;
364
365	preempt_disable();
366	data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
367	__trace_mmiotrace_map(tr, data, map);
368	preempt_enable();
369}
370
371int mmio_trace_printk(const char *fmt, va_list args)
372{
373	return trace_vprintk(0, fmt, args);
374}
v4.6
  1/*
  2 * Memory mapped I/O tracing
  3 *
  4 * Copyright (C) 2008 Pekka Paalanen <pq@iki.fi>
  5 */
  6
  7#define DEBUG 1
  8
  9#include <linux/kernel.h>
 10#include <linux/mmiotrace.h>
 11#include <linux/pci.h>
 12#include <linux/slab.h>
 13#include <linux/time.h>
 14
 15#include <linux/atomic.h>
 16
 17#include "trace.h"
 18#include "trace_output.h"
 19
 20struct header_iter {
 21	struct pci_dev *dev;
 22};
 23
 24static struct trace_array *mmio_trace_array;
 25static bool overrun_detected;
 26static unsigned long prev_overruns;
 27static atomic_t dropped_count;
 28
 29static void mmio_reset_data(struct trace_array *tr)
 30{
 31	overrun_detected = false;
 32	prev_overruns = 0;
 33
 34	tracing_reset_online_cpus(&tr->trace_buffer);
 35}
 36
 37static int mmio_trace_init(struct trace_array *tr)
 38{
 39	pr_debug("in %s\n", __func__);
 40	mmio_trace_array = tr;
 41
 42	mmio_reset_data(tr);
 43	enable_mmiotrace();
 44	return 0;
 45}
 46
 47static void mmio_trace_reset(struct trace_array *tr)
 48{
 49	pr_debug("in %s\n", __func__);
 50
 51	disable_mmiotrace();
 52	mmio_reset_data(tr);
 53	mmio_trace_array = NULL;
 54}
 55
 56static void mmio_trace_start(struct trace_array *tr)
 57{
 58	pr_debug("in %s\n", __func__);
 59	mmio_reset_data(tr);
 60}
 61
 62static void mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
 63{
 
 64	int i;
 65	resource_size_t start, end;
 66	const struct pci_driver *drv = pci_dev_driver(dev);
 67
 68	trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
 69			 dev->bus->number, dev->devfn,
 70			 dev->vendor, dev->device, dev->irq);
 
 71	/*
 72	 * XXX: is pci_resource_to_user() appropriate, since we are
 73	 * supposed to interpret the __ioremap() phys_addr argument based on
 74	 * these printed values?
 75	 */
 76	for (i = 0; i < 7; i++) {
 77		pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
 78		trace_seq_printf(s, " %llx",
 79			(unsigned long long)(start |
 80			(dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
 81	}
 82	for (i = 0; i < 7; i++) {
 83		pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
 84		trace_seq_printf(s, " %llx",
 85			dev->resource[i].start < dev->resource[i].end ?
 86			(unsigned long long)(end - start) + 1 : 0);
 87	}
 88	if (drv)
 89		trace_seq_printf(s, " %s\n", drv->name);
 90	else
 91		trace_seq_puts(s, " \n");
 
 92}
 93
 94static void destroy_header_iter(struct header_iter *hiter)
 95{
 96	if (!hiter)
 97		return;
 98	pci_dev_put(hiter->dev);
 99	kfree(hiter);
100}
101
102static void mmio_pipe_open(struct trace_iterator *iter)
103{
104	struct header_iter *hiter;
105	struct trace_seq *s = &iter->seq;
106
107	trace_seq_puts(s, "VERSION 20070824\n");
108
109	hiter = kzalloc(sizeof(*hiter), GFP_KERNEL);
110	if (!hiter)
111		return;
112
113	hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
114	iter->private = hiter;
115}
116
117/* XXX: This is not called when the pipe is closed! */
118static void mmio_close(struct trace_iterator *iter)
119{
120	struct header_iter *hiter = iter->private;
121	destroy_header_iter(hiter);
122	iter->private = NULL;
123}
124
125static unsigned long count_overruns(struct trace_iterator *iter)
126{
127	unsigned long cnt = atomic_xchg(&dropped_count, 0);
128	unsigned long over = ring_buffer_overruns(iter->trace_buffer->buffer);
129
130	if (over > prev_overruns)
131		cnt += over - prev_overruns;
132	prev_overruns = over;
133	return cnt;
134}
135
136static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp,
137				char __user *ubuf, size_t cnt, loff_t *ppos)
138{
139	ssize_t ret;
140	struct header_iter *hiter = iter->private;
141	struct trace_seq *s = &iter->seq;
142	unsigned long n;
143
144	n = count_overruns(iter);
145	if (n) {
146		/* XXX: This is later than where events were lost. */
147		trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n);
148		if (!overrun_detected)
149			pr_warn("mmiotrace has lost events\n");
150		overrun_detected = true;
151		goto print_out;
152	}
153
154	if (!hiter)
155		return 0;
156
157	mmio_print_pcidev(s, hiter->dev);
158	hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev);
159
160	if (!hiter->dev) {
161		destroy_header_iter(hiter);
162		iter->private = NULL;
163	}
164
165print_out:
166	ret = trace_seq_to_user(s, ubuf, cnt);
167	return (ret == -EBUSY) ? 0 : ret;
168}
169
170static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
171{
172	struct trace_entry *entry = iter->ent;
173	struct trace_mmiotrace_rw *field;
174	struct mmiotrace_rw *rw;
175	struct trace_seq *s	= &iter->seq;
176	unsigned long long t	= ns2usecs(iter->ts);
177	unsigned long usec_rem	= do_div(t, USEC_PER_SEC);
178	unsigned secs		= (unsigned long)t;
 
179
180	trace_assign_type(field, entry);
181	rw = &field->rw;
182
183	switch (rw->opcode) {
184	case MMIO_READ:
185		trace_seq_printf(s,
186			"R %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
187			rw->width, secs, usec_rem, rw->map_id,
188			(unsigned long long)rw->phys,
189			rw->value, rw->pc, 0);
190		break;
191	case MMIO_WRITE:
192		trace_seq_printf(s,
193			"W %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
194			rw->width, secs, usec_rem, rw->map_id,
195			(unsigned long long)rw->phys,
196			rw->value, rw->pc, 0);
197		break;
198	case MMIO_UNKNOWN_OP:
199		trace_seq_printf(s,
200			"UNKNOWN %u.%06lu %d 0x%llx %02lx,%02lx,"
201			"%02lx 0x%lx %d\n",
202			secs, usec_rem, rw->map_id,
203			(unsigned long long)rw->phys,
204			(rw->value >> 16) & 0xff, (rw->value >> 8) & 0xff,
205			(rw->value >> 0) & 0xff, rw->pc, 0);
206		break;
207	default:
208		trace_seq_puts(s, "rw what?\n");
209		break;
210	}
211
212	return trace_handle_return(s);
 
213}
214
215static enum print_line_t mmio_print_map(struct trace_iterator *iter)
216{
217	struct trace_entry *entry = iter->ent;
218	struct trace_mmiotrace_map *field;
219	struct mmiotrace_map *m;
220	struct trace_seq *s	= &iter->seq;
221	unsigned long long t	= ns2usecs(iter->ts);
222	unsigned long usec_rem	= do_div(t, USEC_PER_SEC);
223	unsigned secs		= (unsigned long)t;
 
224
225	trace_assign_type(field, entry);
226	m = &field->map;
227
228	switch (m->opcode) {
229	case MMIO_PROBE:
230		trace_seq_printf(s,
231			"MAP %u.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
232			secs, usec_rem, m->map_id,
233			(unsigned long long)m->phys, m->virt, m->len,
234			0UL, 0);
235		break;
236	case MMIO_UNPROBE:
237		trace_seq_printf(s,
238			"UNMAP %u.%06lu %d 0x%lx %d\n",
239			secs, usec_rem, m->map_id, 0UL, 0);
240		break;
241	default:
242		trace_seq_puts(s, "map what?\n");
243		break;
244	}
245
246	return trace_handle_return(s);
 
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, USEC_PER_SEC);
257	unsigned secs		= (unsigned long)t;
 
258
259	/* The trailing newline must be in the message. */
260	trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg);
 
 
261
262	return trace_handle_return(s);
263}
264
265static enum print_line_t mmio_print_line(struct trace_iterator *iter)
266{
267	switch (iter->ent->type) {
268	case TRACE_MMIO_RW:
269		return mmio_print_rw(iter);
270	case TRACE_MMIO_MAP:
271		return mmio_print_map(iter);
272	case TRACE_PRINT:
273		return mmio_print_mark(iter);
274	default:
275		return TRACE_TYPE_HANDLED; /* ignore unknown entries */
276	}
277}
278
279static struct tracer mmio_tracer __read_mostly =
280{
281	.name		= "mmiotrace",
282	.init		= mmio_trace_init,
283	.reset		= mmio_trace_reset,
284	.start		= mmio_trace_start,
285	.pipe_open	= mmio_pipe_open,
286	.close		= mmio_close,
287	.read		= mmio_read,
288	.print_line	= mmio_print_line,
289};
290
291__init static int init_mmio_trace(void)
292{
293	return register_tracer(&mmio_tracer);
294}
295device_initcall(init_mmio_trace);
296
297static void __trace_mmiotrace_rw(struct trace_array *tr,
298				struct trace_array_cpu *data,
299				struct mmiotrace_rw *rw)
300{
301	struct trace_event_call *call = &event_mmiotrace_rw;
302	struct ring_buffer *buffer = tr->trace_buffer.buffer;
303	struct ring_buffer_event *event;
304	struct trace_mmiotrace_rw *entry;
305	int pc = preempt_count();
306
307	event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW,
308					  sizeof(*entry), 0, pc);
309	if (!event) {
310		atomic_inc(&dropped_count);
311		return;
312	}
313	entry	= ring_buffer_event_data(event);
314	entry->rw			= *rw;
315
316	if (!call_filter_check_discard(call, entry, buffer, event))
317		trace_buffer_unlock_commit(tr, buffer, event, 0, pc);
318}
319
320void mmio_trace_rw(struct mmiotrace_rw *rw)
321{
322	struct trace_array *tr = mmio_trace_array;
323	struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
324	__trace_mmiotrace_rw(tr, data, rw);
325}
326
327static void __trace_mmiotrace_map(struct trace_array *tr,
328				struct trace_array_cpu *data,
329				struct mmiotrace_map *map)
330{
331	struct trace_event_call *call = &event_mmiotrace_map;
332	struct ring_buffer *buffer = tr->trace_buffer.buffer;
333	struct ring_buffer_event *event;
334	struct trace_mmiotrace_map *entry;
335	int pc = preempt_count();
336
337	event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP,
338					  sizeof(*entry), 0, pc);
339	if (!event) {
340		atomic_inc(&dropped_count);
341		return;
342	}
343	entry	= ring_buffer_event_data(event);
344	entry->map			= *map;
345
346	if (!call_filter_check_discard(call, entry, buffer, event))
347		trace_buffer_unlock_commit(tr, buffer, event, 0, pc);
348}
349
350void mmio_trace_mapping(struct mmiotrace_map *map)
351{
352	struct trace_array *tr = mmio_trace_array;
353	struct trace_array_cpu *data;
354
355	preempt_disable();
356	data = per_cpu_ptr(tr->trace_buffer.data, smp_processor_id());
357	__trace_mmiotrace_map(tr, data, map);
358	preempt_enable();
359}
360
361int mmio_trace_printk(const char *fmt, va_list args)
362{
363	return trace_vprintk(0, fmt, args);
364}