[PATCH, resend] ARM: dma-mapping: don't use the atomic pool for DMA_ATTR_NO_KERNEL_MAPPING
From: Christoph Hellwig <hch@lst.de>
Date: 2019-05-28 06:24:30
Also in:
linux-iommu
Subsystem:
arm port, the rest · Maintainers:
Russell King, Linus Torvalds
DMA allocations with the DMA_ATTR_NO_KERNEL_MAPPING do not return a kernel virtual address for use in driver, but are expected to be used entirely for userspace mappings and/or device private memory. Because of that we don't need to remap them as uncached, and thus don't need the atomic pool for non-blocking allocations. Note that using the DMA allocator with DMA_ATTR_NO_KERNEL_MAPPING from non-blocking context on a non-coherent device is actually broken without this patch as well, as we feed the address passes to dma_free_attrs directly to the genpool allocator, but for DMA_ATTR_NO_KERNEL_MAPPING allocations it actually contains the address of the first page pointer. Signed-off-by: Christoph Hellwig <hch@lst.de> --- arch/arm/mm/dma-mapping.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0a75058c11f3..30e891f54d36 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c@@ -724,6 +724,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, pgprot_t prot, bool is_coherent, unsigned long attrs, const void *caller) { + bool want_vaddr = !(attrs & DMA_ATTR_NO_KERNEL_MAPPING); u64 mask = get_coherent_dma_mask(dev); struct page *page = NULL; void *addr;
@@ -735,7 +736,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, .gfp = gfp, .prot = prot, .caller = caller, - .want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0), + .want_vaddr = want_vaddr, .coherent_flag = is_coherent ? COHERENT : NORMAL, };
@@ -773,14 +774,14 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, allowblock = gfpflags_allow_blocking(gfp); cma = allowblock ? dev_get_cma_area(dev) : false; - if (cma) + if (!allowblock && !is_coherent && want_vaddr) + buf->allocator = &pool_allocator; + else if (cma) buf->allocator = &cma_allocator; else if (is_coherent) buf->allocator = &simple_allocator; - else if (allowblock) - buf->allocator = &remap_allocator; else - buf->allocator = &pool_allocator; + buf->allocator = &remap_allocator; addr = buf->allocator->alloc(&args, &page);
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel