* [PATCH v2 0/4] dma-mapping: Trace more error paths
@ 2024-10-18 15:00 Sean Anderson
2024-10-18 15:00 ` [PATCH v2 1/4] dma-mapping: Use macros to define events in a class Sean Anderson
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Sean Anderson @ 2024-10-18 15:00 UTC (permalink / raw)
To: Christoph Hellwig, iommu
Cc: Robin Murphy, linux-trace-kernel, Mathieu Desnoyers,
Steven Rostedt, Masami Hiramatsu, Marek Szyprowski, linux-kernel,
Sean Anderson
Some DMA functions are not traced when they fail. I found this pretty
confusing, since it seems like the device skips calling the DMA function
and fails anyway. This series adds some additional tracepoints to
address this.
Changes in v2:
- Use macros to define events in a class
Sean Anderson (4):
dma-mapping: Use macros to define events in a class
dma-mapping: Trace dma_alloc/free direction
dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using
trace_dma_map
dma-mapping: Trace more error paths
include/trace/events/dma.h | 213 ++++++++++++++++++++++++++++++-------
kernel/dma/mapping.c | 37 ++++---
2 files changed, 198 insertions(+), 52 deletions(-)
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/4] dma-mapping: Use macros to define events in a class
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
@ 2024-10-18 15:00 ` Sean Anderson
2024-10-18 15:00 ` [PATCH v2 2/4] dma-mapping: Trace dma_alloc/free direction Sean Anderson
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sean Anderson @ 2024-10-18 15:00 UTC (permalink / raw)
To: Christoph Hellwig, iommu
Cc: Robin Murphy, linux-trace-kernel, Mathieu Desnoyers,
Steven Rostedt, Masami Hiramatsu, Marek Szyprowski, linux-kernel,
Sean Anderson
Use a macro to avoid repeating the parameters and arguments for each event
in a class.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
Changes in v2:
- New
include/trace/events/dma.h | 60 ++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 32 deletions(-)
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index b0f41265191c..3d348cea4d7c 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -65,15 +65,14 @@ DECLARE_EVENT_CLASS(dma_map,
decode_dma_attrs(__entry->attrs))
);
-DEFINE_EVENT(dma_map, dma_map_page,
- TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction dir, unsigned long attrs),
- TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs));
+#define DEFINE_MAP_EVENT(name) \
+DEFINE_EVENT(dma_map, name, \
+ TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr, \
+ size_t size, enum dma_data_direction dir, unsigned long attrs), \
+ TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs))
-DEFINE_EVENT(dma_map, dma_map_resource,
- TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction dir, unsigned long attrs),
- TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs));
+DEFINE_MAP_EVENT(dma_map_page);
+DEFINE_MAP_EVENT(dma_map_resource);
DECLARE_EVENT_CLASS(dma_unmap,
TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
@@ -104,15 +103,14 @@ DECLARE_EVENT_CLASS(dma_unmap,
decode_dma_attrs(__entry->attrs))
);
-DEFINE_EVENT(dma_unmap, dma_unmap_page,
- TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir, unsigned long attrs),
- TP_ARGS(dev, addr, size, dir, attrs));
+#define DEFINE_UNMAP_EVENT(name) \
+DEFINE_EVENT(dma_unmap, name, \
+ TP_PROTO(struct device *dev, dma_addr_t addr, size_t size, \
+ enum dma_data_direction dir, unsigned long attrs), \
+ TP_ARGS(dev, addr, size, dir, attrs))
-DEFINE_EVENT(dma_unmap, dma_unmap_resource,
- TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir, unsigned long attrs),
- TP_ARGS(dev, addr, size, dir, attrs));
+DEFINE_UNMAP_EVENT(dma_unmap_page);
+DEFINE_UNMAP_EVENT(dma_unmap_resource);
TRACE_EVENT(dma_alloc,
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
@@ -279,15 +277,14 @@ DECLARE_EVENT_CLASS(dma_sync_single,
__entry->size)
);
-DEFINE_EVENT(dma_sync_single, dma_sync_single_for_cpu,
- TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir),
- TP_ARGS(dev, dma_addr, size, dir));
+#define DEFINE_SYNC_SINGLE_EVENT(name) \
+DEFINE_EVENT(dma_sync_single, name, \
+ TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size, \
+ enum dma_data_direction dir), \
+ TP_ARGS(dev, dma_addr, size, dir))
-DEFINE_EVENT(dma_sync_single, dma_sync_single_for_device,
- TP_PROTO(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir),
- TP_ARGS(dev, dma_addr, size, dir));
+DEFINE_SYNC_SINGLE_EVENT(dma_sync_single_for_cpu);
+DEFINE_SYNC_SINGLE_EVENT(dma_sync_single_for_device);
DECLARE_EVENT_CLASS(dma_sync_sg,
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
@@ -326,15 +323,14 @@ DECLARE_EVENT_CLASS(dma_sync_sg,
sizeof(unsigned int), sizeof(unsigned int)))
);
-DEFINE_EVENT(dma_sync_sg, dma_sync_sg_for_cpu,
- TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir),
- TP_ARGS(dev, sg, nents, dir));
+#define DEFINE_SYNC_SG_EVENT(name) \
+DEFINE_EVENT(dma_sync_sg, name, \
+ TP_PROTO(struct device *dev, struct scatterlist *sg, int nents, \
+ enum dma_data_direction dir), \
+ TP_ARGS(dev, sg, nents, dir))
-DEFINE_EVENT(dma_sync_sg, dma_sync_sg_for_device,
- TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir),
- TP_ARGS(dev, sg, nents, dir));
+DEFINE_SYNC_SG_EVENT(dma_sync_sg_for_cpu);
+DEFINE_SYNC_SG_EVENT(dma_sync_sg_for_device);
#endif /* _TRACE_DMA_H */
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/4] dma-mapping: Trace dma_alloc/free direction
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
2024-10-18 15:00 ` [PATCH v2 1/4] dma-mapping: Use macros to define events in a class Sean Anderson
@ 2024-10-18 15:00 ` Sean Anderson
2024-10-18 15:00 ` [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map Sean Anderson
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sean Anderson @ 2024-10-18 15:00 UTC (permalink / raw)
To: Christoph Hellwig, iommu
Cc: Robin Murphy, linux-trace-kernel, Mathieu Desnoyers,
Steven Rostedt, Masami Hiramatsu, Marek Szyprowski, linux-kernel,
Sean Anderson
In preparation for using these tracepoints in a few more places, trace
the DMA direction as well. For coherent allocations this is always
bidirectional.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
(no changes since v1)
include/trace/events/dma.h | 18 ++++++++++++------
kernel/dma/mapping.c | 6 ++++--
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index 3d348cea4d7c..267cfa49d9d5 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -114,8 +114,9 @@ DEFINE_UNMAP_EVENT(dma_unmap_resource);
TRACE_EVENT(dma_alloc,
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
- size_t size, gfp_t flags, unsigned long attrs),
- TP_ARGS(dev, virt_addr, dma_addr, size, flags, attrs),
+ size_t size, enum dma_data_direction dir, gfp_t flags,
+ unsigned long attrs),
+ TP_ARGS(dev, virt_addr, dma_addr, size, dir, flags, attrs),
TP_STRUCT__entry(
__string(device, dev_name(dev))
@@ -123,6 +124,7 @@ TRACE_EVENT(dma_alloc,
__field(u64, dma_addr)
__field(size_t, size)
__field(gfp_t, flags)
+ __field(enum dma_data_direction, dir)
__field(unsigned long, attrs)
),
@@ -135,8 +137,9 @@ TRACE_EVENT(dma_alloc,
__entry->attrs = attrs;
),
- TP_printk("%s dma_addr=%llx size=%zu virt_addr=%p flags=%s attrs=%s",
+ TP_printk("%s dir=%s dma_addr=%llx size=%zu virt_addr=%p flags=%s attrs=%s",
__get_str(device),
+ decode_dma_data_direction(__entry->dir),
__entry->dma_addr,
__entry->size,
__entry->virt_addr,
@@ -146,14 +149,15 @@ TRACE_EVENT(dma_alloc,
TRACE_EVENT(dma_free,
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
- size_t size, unsigned long attrs),
- TP_ARGS(dev, virt_addr, dma_addr, size, attrs),
+ size_t size, enum dma_data_direction dir, unsigned long attrs),
+ TP_ARGS(dev, virt_addr, dma_addr, size, dir, attrs),
TP_STRUCT__entry(
__string(device, dev_name(dev))
__field(void *, virt_addr)
__field(u64, dma_addr)
__field(size_t, size)
+ __field(enum dma_data_direction, dir)
__field(unsigned long, attrs)
),
@@ -162,11 +166,13 @@ TRACE_EVENT(dma_free,
__entry->virt_addr = virt_addr;
__entry->dma_addr = dma_addr;
__entry->size = size;
+ __entry->dir = dir;
__entry->attrs = attrs;
),
- TP_printk("%s dma_addr=%llx size=%zu virt_addr=%p attrs=%s",
+ TP_printk("%s dir=%s dma_addr=%llx size=%zu virt_addr=%p attrs=%s",
__get_str(device),
+ decode_dma_data_direction(__entry->dir),
__entry->dma_addr,
__entry->size,
__entry->virt_addr,
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 864a1121bf08..944ac835030a 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -619,7 +619,8 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
else
return NULL;
- trace_dma_alloc(dev, cpu_addr, *dma_handle, size, flag, attrs);
+ trace_dma_alloc(dev, cpu_addr, *dma_handle, size, DMA_BIDIRECTIONAL,
+ flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr, attrs);
return cpu_addr;
}
@@ -644,7 +645,8 @@ void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
if (!cpu_addr)
return;
- trace_dma_free(dev, cpu_addr, dma_handle, size, attrs);
+ trace_dma_free(dev, cpu_addr, dma_handle, size, DMA_BIDIRECTIONAL,
+ attrs);
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
if (dma_alloc_direct(dev, ops))
dma_direct_free(dev, size, cpu_addr, dma_handle, attrs);
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
2024-10-18 15:00 ` [PATCH v2 1/4] dma-mapping: Use macros to define events in a class Sean Anderson
2024-10-18 15:00 ` [PATCH v2 2/4] dma-mapping: Trace dma_alloc/free direction Sean Anderson
@ 2024-10-18 15:00 ` Sean Anderson
2024-10-25 2:19 ` Steven Rostedt
2024-10-18 15:00 ` [PATCH v2 4/4] dma-mapping: Trace more error paths Sean Anderson
2024-10-23 5:30 ` [PATCH v2 0/4] " Christoph Hellwig
4 siblings, 1 reply; 7+ messages in thread
From: Sean Anderson @ 2024-10-18 15:00 UTC (permalink / raw)
To: Christoph Hellwig, iommu
Cc: Robin Murphy, linux-trace-kernel, Mathieu Desnoyers,
Steven Rostedt, Masami Hiramatsu, Marek Szyprowski, linux-kernel,
Sean Anderson
In some cases, we use trace_dma_map to trace dma_alloc* functions. This
generally follows dma_debug. However, this does not record all of the
relevant information for allocations, such as GFP flags. Create new
dma_alloc tracepoints for these functions. Note that while
dma_alloc_noncontiguous may allocate discontiguous pages (from the CPU's
point of view), the device will only see one contiguous mapping.
Therefore, we just need to trace dma_addr and size.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
Changes in v2:
- Use macros to define events in a class
include/trace/events/dma.h | 99 +++++++++++++++++++++++++++++++++++++-
kernel/dma/mapping.c | 10 ++--
2 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index 267cfa49d9d5..7a9606b8934e 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -112,7 +112,7 @@ DEFINE_EVENT(dma_unmap, name, \
DEFINE_UNMAP_EVENT(dma_unmap_page);
DEFINE_UNMAP_EVENT(dma_unmap_resource);
-TRACE_EVENT(dma_alloc,
+DECLARE_EVENT_CLASS(dma_alloc_class,
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir, gfp_t flags,
unsigned long attrs),
@@ -147,7 +147,58 @@ TRACE_EVENT(dma_alloc,
decode_dma_attrs(__entry->attrs))
);
-TRACE_EVENT(dma_free,
+#define DEFINE_ALLOC_EVENT(name) \
+DEFINE_EVENT(dma_alloc_class, name, \
+ TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr, \
+ size_t size, enum dma_data_direction dir, gfp_t flags, \
+ unsigned long attrs), \
+ TP_ARGS(dev, virt_addr, dma_addr, size, dir, flags, attrs))
+
+DEFINE_ALLOC_EVENT(dma_alloc);
+DEFINE_ALLOC_EVENT(dma_alloc_pages);
+
+TRACE_EVENT(dma_alloc_sgt,
+ TP_PROTO(struct device *dev, struct sg_table *sgt, size_t size,
+ enum dma_data_direction dir, gfp_t flags, unsigned long attrs),
+ TP_ARGS(dev, sgt, size, dir, flags, attrs),
+
+ TP_STRUCT__entry(
+ __string(device, dev_name(dev))
+ __dynamic_array(u64, phys_addrs, sgt->orig_nents)
+ __field(u64, dma_addr)
+ __field(size_t, size)
+ __field(enum dma_data_direction, dir)
+ __field(gfp_t, flags)
+ __field(unsigned long, attrs)
+ ),
+
+ TP_fast_assign(
+ struct scatterlist *sg;
+ int i;
+
+ __assign_str(device);
+ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
+ ((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
+ __entry->dma_addr = sg_dma_address(sgt->sgl);
+ __entry->size = size;
+ __entry->dir = dir;
+ __entry->flags = flags;
+ __entry->attrs = attrs;
+ ),
+
+ TP_printk("%s dir=%s dma_addr=%llx size=%zu phys_addrs=%s flags=%s attrs=%s",
+ __get_str(device),
+ decode_dma_data_direction(__entry->dir),
+ __entry->dma_addr,
+ __entry->size,
+ __print_array(__get_dynamic_array(phys_addrs),
+ __get_dynamic_array_len(phys_addrs) /
+ sizeof(u64), sizeof(u64)),
+ show_gfp_flags(__entry->flags),
+ decode_dma_attrs(__entry->attrs))
+);
+
+DECLARE_EVENT_CLASS(dma_free_class,
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs),
TP_ARGS(dev, virt_addr, dma_addr, size, dir, attrs),
@@ -179,6 +230,50 @@ TRACE_EVENT(dma_free,
decode_dma_attrs(__entry->attrs))
);
+#define DEFINE_FREE_EVENT(name) \
+DEFINE_EVENT(dma_free_class, name, \
+ TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr, \
+ size_t size, enum dma_data_direction dir, unsigned long attrs), \
+ TP_ARGS(dev, virt_addr, dma_addr, size, dir, attrs))
+
+DEFINE_FREE_EVENT(dma_free);
+DEFINE_FREE_EVENT(dma_free_pages);
+
+TRACE_EVENT(dma_free_sgt,
+ TP_PROTO(struct device *dev, struct sg_table *sgt, size_t size,
+ enum dma_data_direction dir),
+ TP_ARGS(dev, sgt, size, dir),
+
+ TP_STRUCT__entry(
+ __string(device, dev_name(dev))
+ __dynamic_array(u64, phys_addrs, sgt->orig_nents)
+ __field(u64, dma_addr)
+ __field(size_t, size)
+ __field(enum dma_data_direction, dir)
+ ),
+
+ TP_fast_assign(
+ struct scatterlist *sg;
+ int i;
+
+ __assign_str(device);
+ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
+ ((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
+ __entry->dma_addr = sg_dma_address(sgt->sgl);
+ __entry->size = size;
+ __entry->dir = dir;
+ ),
+
+ TP_printk("%s dir=%s dma_addr=%llx size=%zu phys_addrs=%s",
+ __get_str(device),
+ decode_dma_data_direction(__entry->dir),
+ __entry->dma_addr,
+ __entry->size,
+ __print_array(__get_dynamic_array(phys_addrs),
+ __get_dynamic_array_len(phys_addrs) /
+ sizeof(u64), sizeof(u64)))
+);
+
TRACE_EVENT(dma_map_sg,
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
int ents, enum dma_data_direction dir, unsigned long attrs),
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 944ac835030a..b8a6bc492fae 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -685,8 +685,8 @@ struct page *dma_alloc_pages(struct device *dev, size_t size,
struct page *page = __dma_alloc_pages(dev, size, dma_handle, dir, gfp);
if (page) {
- trace_dma_map_page(dev, page_to_phys(page), *dma_handle, size,
- dir, 0);
+ trace_dma_alloc_pages(dev, page_to_virt(page), *dma_handle,
+ size, dir, gfp, 0);
debug_dma_map_page(dev, page, 0, size, dir, *dma_handle, 0);
}
return page;
@@ -710,7 +710,7 @@ static void __dma_free_pages(struct device *dev, size_t size, struct page *page,
void dma_free_pages(struct device *dev, size_t size, struct page *page,
dma_addr_t dma_handle, enum dma_data_direction dir)
{
- trace_dma_unmap_page(dev, dma_handle, size, dir, 0);
+ trace_dma_free_pages(dev, page_to_virt(page), dma_handle, size, dir, 0);
debug_dma_unmap_page(dev, dma_handle, size, dir);
__dma_free_pages(dev, size, page, dma_handle, dir);
}
@@ -770,7 +770,7 @@ struct sg_table *dma_alloc_noncontiguous(struct device *dev, size_t size,
if (sgt) {
sgt->nents = 1;
- trace_dma_map_sg(dev, sgt->sgl, sgt->orig_nents, 1, dir, attrs);
+ trace_dma_alloc_sgt(dev, sgt, size, dir, gfp, attrs);
debug_dma_map_sg(dev, sgt->sgl, sgt->orig_nents, 1, dir, attrs);
}
return sgt;
@@ -789,7 +789,7 @@ static void free_single_sgt(struct device *dev, size_t size,
void dma_free_noncontiguous(struct device *dev, size_t size,
struct sg_table *sgt, enum dma_data_direction dir)
{
- trace_dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir, 0);
+ trace_dma_free_sgt(dev, sgt, size, dir);
debug_dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
if (use_dma_iommu(dev))
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/4] dma-mapping: Trace more error paths
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
` (2 preceding siblings ...)
2024-10-18 15:00 ` [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map Sean Anderson
@ 2024-10-18 15:00 ` Sean Anderson
2024-10-23 5:30 ` [PATCH v2 0/4] " Christoph Hellwig
4 siblings, 0 replies; 7+ messages in thread
From: Sean Anderson @ 2024-10-18 15:00 UTC (permalink / raw)
To: Christoph Hellwig, iommu
Cc: Robin Murphy, linux-trace-kernel, Mathieu Desnoyers,
Steven Rostedt, Masami Hiramatsu, Marek Szyprowski, linux-kernel,
Sean Anderson
It can be surprising to the user if DMA functions are only traced on
success. On failure, it can be unclear what the source of the problem
is. Fix this by tracing all functions even when they fail. Cases where
we BUG/WARN are skipped, since those should be sufficiently noisy
already.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
---
Changes in v2:
- Use macros to define events in a class
include/trace/events/dma.h | 36 ++++++++++++++++++++++++++++++++++++
kernel/dma/mapping.c | 27 +++++++++++++++++++--------
2 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index 7a9606b8934e..d8ddc27b6a7c 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -156,6 +156,7 @@ DEFINE_EVENT(dma_alloc_class, name, \
DEFINE_ALLOC_EVENT(dma_alloc);
DEFINE_ALLOC_EVENT(dma_alloc_pages);
+DEFINE_ALLOC_EVENT(dma_alloc_sgt_err);
TRACE_EVENT(dma_alloc_sgt,
TP_PROTO(struct device *dev, struct sg_table *sgt, size_t size,
@@ -320,6 +321,41 @@ TRACE_EVENT(dma_map_sg,
decode_dma_attrs(__entry->attrs))
);
+TRACE_EVENT(dma_map_sg_err,
+ TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
+ int err, enum dma_data_direction dir, unsigned long attrs),
+ TP_ARGS(dev, sgl, nents, err, dir, attrs),
+
+ TP_STRUCT__entry(
+ __string(device, dev_name(dev))
+ __dynamic_array(u64, phys_addrs, nents)
+ __field(int, err)
+ __field(enum dma_data_direction, dir)
+ __field(unsigned long, attrs)
+ ),
+
+ TP_fast_assign(
+ struct scatterlist *sg;
+ int i;
+
+ __assign_str(device);
+ for_each_sg(sgl, sg, nents, i)
+ ((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
+ __entry->err = err;
+ __entry->dir = dir;
+ __entry->attrs = attrs;
+ ),
+
+ TP_printk("%s dir=%s dma_addrs=%s err=%d attrs=%s",
+ __get_str(device),
+ decode_dma_data_direction(__entry->dir),
+ __print_array(__get_dynamic_array(phys_addrs),
+ __get_dynamic_array_len(phys_addrs) /
+ sizeof(u64), sizeof(u64)),
+ __entry->err,
+ decode_dma_attrs(__entry->attrs))
+);
+
TRACE_EVENT(dma_unmap_sg,
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
enum dma_data_direction dir, unsigned long attrs),
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index b8a6bc492fae..636dbb0629a4 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -223,6 +223,7 @@ static int __dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
debug_dma_map_sg(dev, sg, nents, ents, dir, attrs);
} else if (WARN_ON_ONCE(ents != -EINVAL && ents != -ENOMEM &&
ents != -EIO && ents != -EREMOTEIO)) {
+ trace_dma_map_sg_err(dev, sg, nents, ents, dir, attrs);
return -EIO;
}
@@ -604,20 +605,26 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
if (WARN_ON_ONCE(flag & __GFP_COMP))
return NULL;
- if (dma_alloc_from_dev_coherent(dev, size, dma_handle, &cpu_addr))
+ if (dma_alloc_from_dev_coherent(dev, size, dma_handle, &cpu_addr)) {
+ trace_dma_alloc(dev, cpu_addr, *dma_handle, size,
+ DMA_BIDIRECTIONAL, flag, attrs);
return cpu_addr;
+ }
/* let the implementation decide on the zone to allocate from: */
flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
- if (dma_alloc_direct(dev, ops))
+ if (dma_alloc_direct(dev, ops)) {
cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
- else if (use_dma_iommu(dev))
+ } else if (use_dma_iommu(dev)) {
cpu_addr = iommu_dma_alloc(dev, size, dma_handle, flag, attrs);
- else if (ops->alloc)
+ } else if (ops->alloc) {
cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
- else
+ } else {
+ trace_dma_alloc(dev, NULL, 0, size, DMA_BIDIRECTIONAL, flag,
+ attrs);
return NULL;
+ }
trace_dma_alloc(dev, cpu_addr, *dma_handle, size, DMA_BIDIRECTIONAL,
flag, attrs);
@@ -642,11 +649,11 @@ void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
*/
WARN_ON(irqs_disabled());
- if (!cpu_addr)
- return;
-
trace_dma_free(dev, cpu_addr, dma_handle, size, DMA_BIDIRECTIONAL,
attrs);
+ if (!cpu_addr)
+ return;
+
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
if (dma_alloc_direct(dev, ops))
dma_direct_free(dev, size, cpu_addr, dma_handle, attrs);
@@ -688,6 +695,8 @@ struct page *dma_alloc_pages(struct device *dev, size_t size,
trace_dma_alloc_pages(dev, page_to_virt(page), *dma_handle,
size, dir, gfp, 0);
debug_dma_map_page(dev, page, 0, size, dir, *dma_handle, 0);
+ } else {
+ trace_dma_alloc_pages(dev, NULL, 0, size, dir, gfp, 0);
}
return page;
}
@@ -772,6 +781,8 @@ struct sg_table *dma_alloc_noncontiguous(struct device *dev, size_t size,
sgt->nents = 1;
trace_dma_alloc_sgt(dev, sgt, size, dir, gfp, attrs);
debug_dma_map_sg(dev, sgt->sgl, sgt->orig_nents, 1, dir, attrs);
+ } else {
+ trace_dma_alloc_sgt_err(dev, NULL, 0, size, gfp, dir, attrs);
}
return sgt;
}
--
2.35.1.1320.gc452695387.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 0/4] dma-mapping: Trace more error paths
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
` (3 preceding siblings ...)
2024-10-18 15:00 ` [PATCH v2 4/4] dma-mapping: Trace more error paths Sean Anderson
@ 2024-10-23 5:30 ` Christoph Hellwig
4 siblings, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2024-10-23 5:30 UTC (permalink / raw)
To: Sean Anderson
Cc: Christoph Hellwig, iommu, Robin Murphy, linux-trace-kernel,
Mathieu Desnoyers, Steven Rostedt, Masami Hiramatsu,
Marek Szyprowski, linux-kernel
Hi Sean,
the patches looks fine to me. I'll wait a bit for more feedback but
plan to pick them up for Linux 6.13.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map
2024-10-18 15:00 ` [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map Sean Anderson
@ 2024-10-25 2:19 ` Steven Rostedt
0 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2024-10-25 2:19 UTC (permalink / raw)
To: Sean Anderson
Cc: Christoph Hellwig, iommu, Robin Murphy, linux-trace-kernel,
Mathieu Desnoyers, Masami Hiramatsu, Marek Szyprowski,
linux-kernel
On Fri, 18 Oct 2024 11:00:36 -0400
Sean Anderson <sean.anderson@linux.dev> wrote:
> + TP_printk("%s dir=%s dma_addr=%llx size=%zu phys_addrs=%s flags=%s attrs=%s",
> + __get_str(device),
> + decode_dma_data_direction(__entry->dir),
> + __entry->dma_addr,
> + __entry->size,
> + __print_array(__get_dynamic_array(phys_addrs),
> + __get_dynamic_array_len(phys_addrs) /
> + sizeof(u64), sizeof(u64)),
> + show_gfp_flags(__entry->flags),
> + decode_dma_attrs(__entry->attrs))
From a tracing perspective, everything in the patch set looks good.
Just a heads up that the above __print_array() should be changed after
6.13 is out to use __print_dynamic_array().
https://lore.kernel.org/linux-trace-kernel/20241022194158.110073-3-avadhut.naik@amd.com/
For the series:
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-- Steve
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-10-25 2:20 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-18 15:00 [PATCH v2 0/4] dma-mapping: Trace more error paths Sean Anderson
2024-10-18 15:00 ` [PATCH v2 1/4] dma-mapping: Use macros to define events in a class Sean Anderson
2024-10-18 15:00 ` [PATCH v2 2/4] dma-mapping: Trace dma_alloc/free direction Sean Anderson
2024-10-18 15:00 ` [PATCH v2 3/4] dma-mapping: Use trace_dma_alloc for dma_alloc* instead of using trace_dma_map Sean Anderson
2024-10-25 2:19 ` Steven Rostedt
2024-10-18 15:00 ` [PATCH v2 4/4] dma-mapping: Trace more error paths Sean Anderson
2024-10-23 5:30 ` [PATCH v2 0/4] " Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).