Skip to content

Commit e6a58fa

Browse files
rleonmszyprow
authored andcommitted
dma-mapping: Introduce DMA require coherency attribute
The mapping buffers which carry this attribute require DMA coherent system. This means that they can't take SWIOTLB path, can perform CPU cache overlap and doesn't perform cache flushing. Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://lore.kernel.org/r/20260316-dma-debug-overlap-v3-4-1dde90a7f08b@nvidia.com
1 parent 9bb0a4d commit e6a58fa

5 files changed

Lines changed: 33 additions & 2 deletions

File tree

Documentation/core-api/dma-attributes.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,19 @@ data corruption.
163163

164164
All mappings that share a cache line must set this attribute to suppress DMA
165165
debug warnings about overlapping mappings.
166+
167+
DMA_ATTR_REQUIRE_COHERENT
168+
-------------------------
169+
170+
DMA mapping requests with the DMA_ATTR_REQUIRE_COHERENT fail on any
171+
system where SWIOTLB or cache management is required. This should only
172+
be used to support uAPI designs that require continuous HW DMA
173+
coherence with userspace processes, for example RDMA and DRM. At a
174+
minimum the memory being mapped must be userspace memory from
175+
pin_user_pages() or similar.
176+
177+
Drivers should consider using dma_mmap_pages() instead of this
178+
interface when building their uAPIs, when possible.
179+
180+
It must never be used in an in-kernel driver that only works with
181+
kernel memory.

include/linux/dma-mapping.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@
8686
*/
8787
#define DMA_ATTR_DEBUGGING_IGNORE_CACHELINES (1UL << 11)
8888

89+
/*
90+
* DMA_ATTR_REQUIRE_COHERENT: Indicates that DMA coherency is required.
91+
* All mappings that carry this attribute can't work with SWIOTLB and cache
92+
* flushing.
93+
*/
94+
#define DMA_ATTR_REQUIRE_COHERENT (1UL << 12)
95+
8996
/*
9097
* A dma_addr_t can hold any valid DMA or bus address for the platform. It can
9198
* be given to a device to use as a DMA source or target. It is specific to a

include/trace/events/dma.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ TRACE_DEFINE_ENUM(DMA_NONE);
3333
{ DMA_ATTR_NO_WARN, "NO_WARN" }, \
3434
{ DMA_ATTR_PRIVILEGED, "PRIVILEGED" }, \
3535
{ DMA_ATTR_MMIO, "MMIO" }, \
36-
{ DMA_ATTR_DEBUGGING_IGNORE_CACHELINES, "CACHELINES_OVERLAP" })
36+
{ DMA_ATTR_DEBUGGING_IGNORE_CACHELINES, "CACHELINES_OVERLAP" }, \
37+
{ DMA_ATTR_REQUIRE_COHERENT, "REQUIRE_COHERENT" })
3738

3839
DECLARE_EVENT_CLASS(dma_map,
3940
TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,

kernel/dma/debug.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,8 @@ static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs)
601601
unsigned long flags;
602602
int rc;
603603

604-
entry->is_cache_clean = attrs & DMA_ATTR_DEBUGGING_IGNORE_CACHELINES;
604+
entry->is_cache_clean = attrs & (DMA_ATTR_DEBUGGING_IGNORE_CACHELINES |
605+
DMA_ATTR_REQUIRE_COHERENT);
605606

606607
bucket = get_hash_bucket(entry, &flags);
607608
hash_bucket_add(bucket, entry);

kernel/dma/mapping.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
164164
if (WARN_ON_ONCE(!dev->dma_mask))
165165
return DMA_MAPPING_ERROR;
166166

167+
if (!dev_is_dma_coherent(dev) && (attrs & DMA_ATTR_REQUIRE_COHERENT))
168+
return DMA_MAPPING_ERROR;
169+
167170
if (dma_map_direct(dev, ops) ||
168171
(!is_mmio && arch_dma_map_phys_direct(dev, phys + size)))
169172
addr = dma_direct_map_phys(dev, phys, size, dir, attrs);
@@ -235,6 +238,9 @@ static int __dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
235238

236239
BUG_ON(!valid_dma_direction(dir));
237240

241+
if (!dev_is_dma_coherent(dev) && (attrs & DMA_ATTR_REQUIRE_COHERENT))
242+
return -EOPNOTSUPP;
243+
238244
if (WARN_ON_ONCE(!dev->dma_mask))
239245
return 0;
240246

0 commit comments

Comments
 (0)