summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@nvidia.com>2026-05-01 09:35:10 +0300
committerMarek Szyprowski <m.szyprowski@samsung.com>2026-05-08 23:28:19 +0300
commita34bd60bdaebb1db4631cad45ff87dcabf4fc962 (patch)
treefb67e61d903a8d7aaa6a10db98cfc334fd4a4b78
parentc8411b1d1e524cbe4a12aacad7bf2163fb2be062 (diff)
downloadlinux-a34bd60bdaebb1db4631cad45ff87dcabf4fc962.tar.xz
dma-debug: Ensure mappings are created and released with matching attributes
The DMA API expects that callers use the same attributes when mapping and unmapping. Add tracking to verify this and catch mismatches. Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://lore.kernel.org/r/20260501-dma-attrs-debug-v2-6-8dbac75cd501@nvidia.com
-rw-r--r--kernel/dma/debug.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 3dfed51c3d9a..c38efc1ac8d6 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -1074,6 +1074,29 @@ static void check_unmap(struct dma_debug_entry *ref)
type2name[entry->type]);
}
+ /*
+ * This may be no bug in reality - but DMA API still expects
+ * that entry is unmapped with same attributes as it was mapped.
+ *
+ * DMA_ATTR_UNMAP_VALID lists the attributes that must be identical
+ * between map and unmap. Any attribute outside this set (e.g.
+ * DMA_ATTR_NO_WARN, DMA_ATTR_SKIP_CPU_SYNC) is allowed to differ.
+ */
+#define DMA_ATTR_UNMAP_VALID \
+ (DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_FORCE_CONTIGUOUS | \
+ DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT | DMA_ATTR_PRIVILEGED | \
+ DMA_ATTR_CC_SHARED)
+ if ((ref->attrs & DMA_ATTR_UNMAP_VALID) !=
+ (entry->attrs & DMA_ATTR_UNMAP_VALID)) {
+ err_printk(ref->dev, entry,
+ "device driver frees "
+ "DMA memory with different attributes "
+ "[device address=0x%016llx] [size=%llu bytes] "
+ "[mapped with 0x%lx] [unmapped with 0x%lx]\n",
+ ref->dev_addr, ref->size, entry->attrs, ref->attrs);
+ }
+#undef DMA_ATTR_UNMAP_VALID
+
hash_bucket_del(entry);
put_hash_bucket(bucket, flags);