Skip to content

Commit 038eb43

Browse files
Sean AndersonChristoph Hellwig
authored andcommitted
dma-mapping: add tracing for dma-mapping API calls
When debugging drivers, it can often be useful to trace when memory gets (un)mapped for DMA (and can be accessed by the device). Add some tracepoints for this purpose. Use u64 instead of phys_addr_t and dma_addr_t (and similarly %llx instead of %pa) because libtraceevent can't handle typedefs in all cases. Signed-off-by: Sean Anderson <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 1915626 commit 038eb43

File tree

2 files changed

+364
-1
lines changed

2 files changed

+364
-1
lines changed

include/trace/events/dma.h

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#undef TRACE_SYSTEM
3+
#define TRACE_SYSTEM dma
4+
5+
#if !defined(_TRACE_DMA_H) || defined(TRACE_HEADER_MULTI_READ)
6+
#define _TRACE_DMA_H
7+
8+
#include <linux/tracepoint.h>
9+
#include <linux/dma-direction.h>
10+
#include <linux/dma-mapping.h>
11+
#include <trace/events/mmflags.h>
12+
13+
TRACE_DEFINE_ENUM(DMA_BIDIRECTIONAL);
14+
TRACE_DEFINE_ENUM(DMA_TO_DEVICE);
15+
TRACE_DEFINE_ENUM(DMA_FROM_DEVICE);
16+
TRACE_DEFINE_ENUM(DMA_NONE);
17+
18+
#define decode_dma_data_direction(dir) \
19+
__print_symbolic(dir, \
20+
{ DMA_BIDIRECTIONAL, "BIDIRECTIONAL" }, \
21+
{ DMA_TO_DEVICE, "TO_DEVICE" }, \
22+
{ DMA_FROM_DEVICE, "FROM_DEVICE" }, \
23+
{ DMA_NONE, "NONE" })
24+
25+
#define decode_dma_attrs(attrs) \
26+
__print_flags(attrs, "|", \
27+
{ DMA_ATTR_WEAK_ORDERING, "WEAK_ORDERING" }, \
28+
{ DMA_ATTR_WRITE_COMBINE, "WRITE_COMBINE" }, \
29+
{ DMA_ATTR_NO_KERNEL_MAPPING, "NO_KERNEL_MAPPING" }, \
30+
{ DMA_ATTR_SKIP_CPU_SYNC, "SKIP_CPU_SYNC" }, \
31+
{ DMA_ATTR_FORCE_CONTIGUOUS, "FORCE_CONTIGUOUS" }, \
32+
{ DMA_ATTR_ALLOC_SINGLE_PAGES, "ALLOC_SINGLE_PAGES" }, \
33+
{ DMA_ATTR_NO_WARN, "NO_WARN" }, \
34+
{ DMA_ATTR_PRIVILEGED, "PRIVILEGED" })
35+
36+
DECLARE_EVENT_CLASS(dma_map,
37+
TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
38+
size_t size, enum dma_data_direction dir, unsigned long attrs),
39+
TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs),
40+
41+
TP_STRUCT__entry(
42+
__string(device, dev_name(dev))
43+
__field(u64, phys_addr)
44+
__field(u64, dma_addr)
45+
__field(size_t, size)
46+
__field(enum dma_data_direction, dir)
47+
__field(unsigned long, attrs)
48+
),
49+
50+
TP_fast_assign(
51+
__assign_str(device);
52+
__entry->phys_addr = phys_addr;
53+
__entry->dma_addr = dma_addr;
54+
__entry->size = size;
55+
__entry->dir = dir;
56+
__entry->attrs = attrs;
57+
),
58+
59+
TP_printk("%s dir=%s dma_addr=%llx size=%zu phys_addr=%llx attrs=%s",
60+
__get_str(device),
61+
decode_dma_data_direction(__entry->dir),
62+
__entry->dma_addr,
63+
__entry->size,
64+
__entry->phys_addr,
65+
decode_dma_attrs(__entry->attrs))
66+
);
67+
68+
DEFINE_EVENT(dma_map, dma_map_page,
69+
TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
70+
size_t size, enum dma_data_direction dir, unsigned long attrs),
71+
TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs));
72+
73+
DEFINE_EVENT(dma_map, dma_map_resource,
74+
TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
75+
size_t size, enum dma_data_direction dir, unsigned long attrs),
76+
TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs));
77+
78+
DECLARE_EVENT_CLASS(dma_unmap,
79+
TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
80+
enum dma_data_direction dir, unsigned long attrs),
81+
TP_ARGS(dev, addr, size, dir, attrs),
82+
83+
TP_STRUCT__entry(
84+
__string(device, dev_name(dev))
85+
__field(u64, addr)
86+
__field(size_t, size)
87+
__field(enum dma_data_direction, dir)
88+
__field(unsigned long, attrs)
89+
),
90+
91+
TP_fast_assign(
92+
__assign_str(device);
93+
__entry->addr = addr;
94+
__entry->size = size;
95+
__entry->dir = dir;
96+
__entry->attrs = attrs;
97+
),
98+
99+
TP_printk("%s dir=%s dma_addr=%llx size=%zu attrs=%s",
100+
__get_str(device),
101+
decode_dma_data_direction(__entry->dir),
102+
__entry->addr,
103+
__entry->size,
104+
decode_dma_attrs(__entry->attrs))
105+
);
106+
107+
DEFINE_EVENT(dma_unmap, dma_unmap_page,
108+
TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
109+
enum dma_data_direction dir, unsigned long attrs),
110+
TP_ARGS(dev, addr, size, dir, attrs));
111+
112+
DEFINE_EVENT(dma_unmap, dma_unmap_resource,
113+
TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
114+
enum dma_data_direction dir, unsigned long attrs),
115+
TP_ARGS(dev, addr, size, dir, attrs));
116+
117+
TRACE_EVENT(dma_alloc,
118+
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
119+
size_t size, gfp_t flags, unsigned long attrs),
120+
TP_ARGS(dev, virt_addr, dma_addr, size, flags, attrs),
121+
122+
TP_STRUCT__entry(
123+
__string(device, dev_name(dev))
124+
__field(u64, phys_addr)
125+
__field(u64, dma_addr)
126+
__field(size_t, size)
127+
__field(gfp_t, flags)
128+
__field(unsigned long, attrs)
129+
),
130+
131+
TP_fast_assign(
132+
__assign_str(device);
133+
__entry->phys_addr = virt_to_phys(virt_addr);
134+
__entry->dma_addr = dma_addr;
135+
__entry->size = size;
136+
__entry->flags = flags;
137+
__entry->attrs = attrs;
138+
),
139+
140+
TP_printk("%s dma_addr=%llx size=%zu phys_addr=%llx flags=%s attrs=%s",
141+
__get_str(device),
142+
__entry->dma_addr,
143+
__entry->size,
144+
__entry->phys_addr,
145+
show_gfp_flags(__entry->flags),
146+
decode_dma_attrs(__entry->attrs))
147+
);
148+
149+
TRACE_EVENT(dma_free,
150+
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
151+
size_t size, unsigned long attrs),
152+
TP_ARGS(dev, virt_addr, dma_addr, size, attrs),
153+
154+
TP_STRUCT__entry(
155+
__string(device, dev_name(dev))
156+
__field(u64, phys_addr)
157+
__field(u64, dma_addr)
158+
__field(size_t, size)
159+
__field(unsigned long, attrs)
160+
),
161+
162+
TP_fast_assign(
163+
__assign_str(device);
164+
__entry->phys_addr = virt_to_phys(virt_addr);
165+
__entry->dma_addr = dma_addr;
166+
__entry->size = size;
167+
__entry->attrs = attrs;
168+
),
169+
170+
TP_printk("%s dma_addr=%llx size=%zu phys_addr=%llx attrs=%s",
171+
__get_str(device),
172+
__entry->dma_addr,
173+
__entry->size,
174+
__entry->phys_addr,
175+
decode_dma_attrs(__entry->attrs))
176+
);
177+
178+
TRACE_EVENT(dma_map_sg,
179+
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
180+
int ents, enum dma_data_direction dir, unsigned long attrs),
181+
TP_ARGS(dev, sg, nents, ents, dir, attrs),
182+
183+
TP_STRUCT__entry(
184+
__string(device, dev_name(dev))
185+
__dynamic_array(u64, phys_addrs, nents)
186+
__dynamic_array(u64, dma_addrs, ents)
187+
__dynamic_array(unsigned int, lengths, ents)
188+
__field(enum dma_data_direction, dir)
189+
__field(unsigned long, attrs)
190+
),
191+
192+
TP_fast_assign(
193+
int i;
194+
195+
__assign_str(device);
196+
for (i = 0; i < nents; i++)
197+
((u64 *)__get_dynamic_array(phys_addrs))[i] =
198+
sg_phys(sg + i);
199+
for (i = 0; i < ents; i++) {
200+
((u64 *)__get_dynamic_array(dma_addrs))[i] =
201+
sg_dma_address(sg + i);
202+
((unsigned int *)__get_dynamic_array(lengths))[i] =
203+
sg_dma_len(sg + i);
204+
}
205+
__entry->dir = dir;
206+
__entry->attrs = attrs;
207+
),
208+
209+
TP_printk("%s dir=%s dma_addrs=%s sizes=%s phys_addrs=%s attrs=%s",
210+
__get_str(device),
211+
decode_dma_data_direction(__entry->dir),
212+
__print_array(__get_dynamic_array(dma_addrs),
213+
__get_dynamic_array_len(dma_addrs) /
214+
sizeof(u64), sizeof(u64)),
215+
__print_array(__get_dynamic_array(lengths),
216+
__get_dynamic_array_len(lengths) /
217+
sizeof(unsigned int), sizeof(unsigned int)),
218+
__print_array(__get_dynamic_array(phys_addrs),
219+
__get_dynamic_array_len(phys_addrs) /
220+
sizeof(u64), sizeof(u64)),
221+
decode_dma_attrs(__entry->attrs))
222+
);
223+
224+
TRACE_EVENT(dma_unmap_sg,
225+
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
226+
enum dma_data_direction dir, unsigned long attrs),
227+
TP_ARGS(dev, sg, nents, dir, attrs),
228+
229+
TP_STRUCT__entry(
230+
__string(device, dev_name(dev))
231+
__dynamic_array(u64, addrs, nents)
232+
__field(enum dma_data_direction, dir)
233+
__field(unsigned long, attrs)
234+
),
235+
236+
TP_fast_assign(
237+
int i;
238+
239+
__assign_str(device);
240+
for (i = 0; i < nents; i++)
241+
((u64 *)__get_dynamic_array(addrs))[i] =
242+
sg_phys(sg + i);
243+
__entry->dir = dir;
244+
__entry->attrs = attrs;
245+
),
246+
247+
TP_printk("%s dir=%s phys_addrs=%s attrs=%s",
248+
__get_str(device),
249+
decode_dma_data_direction(__entry->dir),
250+
__print_array(__get_dynamic_array(addrs),
251+
__get_dynamic_array_len(addrs) /
252+
sizeof(u64), sizeof(u64)),
253+
decode_dma_attrs(__entry->attrs))
254+
);
255+
256+
DECLARE_EVENT_CLASS(dma_sync_single,
257+
TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size,
258+
enum dma_data_direction dir),
259+
TP_ARGS(dev, dma_addr, size, dir),
260+
261+
TP_STRUCT__entry(
262+
__string(device, dev_name(dev))
263+
__field(u64, dma_addr)
264+
__field(size_t, size)
265+
__field(enum dma_data_direction, dir)
266+
),
267+
268+
TP_fast_assign(
269+
__assign_str(device);
270+
__entry->dma_addr = dma_addr;
271+
__entry->size = size;
272+
__entry->dir = dir;
273+
),
274+
275+
TP_printk("%s dir=%s dma_addr=%llx size=%zu",
276+
__get_str(device),
277+
decode_dma_data_direction(__entry->dir),
278+
__entry->dma_addr,
279+
__entry->size)
280+
);
281+
282+
DEFINE_EVENT(dma_sync_single, dma_sync_single_for_cpu,
283+
TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size,
284+
enum dma_data_direction dir),
285+
TP_ARGS(dev, dma_addr, size, dir));
286+
287+
DEFINE_EVENT(dma_sync_single, dma_sync_single_for_device,
288+
TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size,
289+
enum dma_data_direction dir),
290+
TP_ARGS(dev, dma_addr, size, dir));
291+
292+
DECLARE_EVENT_CLASS(dma_sync_sg,
293+
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
294+
enum dma_data_direction dir),
295+
TP_ARGS(dev, sg, nents, dir),
296+
297+
TP_STRUCT__entry(
298+
__string(device, dev_name(dev))
299+
__dynamic_array(u64, dma_addrs, nents)
300+
__dynamic_array(unsigned int, lengths, nents)
301+
__field(enum dma_data_direction, dir)
302+
),
303+
304+
TP_fast_assign(
305+
int i;
306+
307+
__assign_str(device);
308+
for (i = 0; i < nents; i++) {
309+
((u64 *)__get_dynamic_array(dma_addrs))[i] =
310+
sg_dma_address(sg + i);
311+
((unsigned int *)__get_dynamic_array(lengths))[i] =
312+
sg_dma_len(sg + i);
313+
}
314+
__entry->dir = dir;
315+
),
316+
317+
TP_printk("%s dir=%s dma_addrs=%s sizes=%s",
318+
__get_str(device),
319+
decode_dma_data_direction(__entry->dir),
320+
__print_array(__get_dynamic_array(dma_addrs),
321+
__get_dynamic_array_len(dma_addrs) /
322+
sizeof(u64), sizeof(u64)),
323+
__print_array(__get_dynamic_array(lengths),
324+
__get_dynamic_array_len(lengths) /
325+
sizeof(unsigned int), sizeof(unsigned int)))
326+
);
327+
328+
DEFINE_EVENT(dma_sync_sg, dma_sync_sg_for_cpu,
329+
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
330+
enum dma_data_direction dir),
331+
TP_ARGS(dev, sg, nents, dir));
332+
333+
DEFINE_EVENT(dma_sync_sg, dma_sync_sg_for_device,
334+
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
335+
enum dma_data_direction dir),
336+
TP_ARGS(dev, sg, nents, dir));
337+
338+
#endif /* _TRACE_DMA_H */
339+
340+
/* This part must be outside protection */
341+
#include <trace/define_trace.h>

0 commit comments

Comments
 (0)