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 <h...@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 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu