dma-direct: fix DMA_ATTR_NO_KERNEL_MAPPING for remapped allocations
authorChristoph Hellwig <hch@lst.de>
Fri, 4 Jan 2019 17:31:48 +0000 (18:31 +0100)
committerChristoph Hellwig <hch@lst.de>
Sat, 5 Jan 2019 07:28:29 +0000 (08:28 +0100)
We need to return a dma_addr_t even if we don't have a kernel mapping.
Do so by consolidating the phys_to_dma call in a single place and jump
to it from all the branches that return successfully.

Fixes: bfd56cd60521 ("dma-mapping: support highmem in the generic remap allocator")
Reported-by: Liviu Dudau <liviu@dudau.co.uk
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Liviu Dudau <liviu@dudau.co.uk>
kernel/dma/remap.c

index 18cc09fc27b92a4fff6670d7916c0de364b1a031..7a723194ecbed71bec2db5265c932c2f84a8b123 100644 (file)
@@ -204,8 +204,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
                ret = dma_alloc_from_pool(size, &page, flags);
                if (!ret)
                        return NULL;
-               *dma_handle = phys_to_dma(dev, page_to_phys(page));
-               return ret;
+               goto done;
        }
 
        page = __dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);
@@ -215,8 +214,10 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
        /* remove any dirty cache lines on the kernel alias */
        arch_dma_prep_coherent(page, size);
 
-       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
-               return page; /* opaque cookie */
+       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+               ret = page; /* opaque cookie */
+               goto done;
+       }
 
        /* create a coherent mapping */
        ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
@@ -227,9 +228,9 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
                return ret;
        }
 
-       *dma_handle = phys_to_dma(dev, page_to_phys(page));
        memset(ret, 0, size);
-
+done:
+       *dma_handle = phys_to_dma(dev, page_to_phys(page));
        return ret;
 }