diff options
author | Christoph Hellwig <hch@lst.de> | 2018-11-04 17:51:50 +0100 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-12-01 18:07:14 +0100 |
commit | e440e26a0251b054243b3db6356f3869a9f9c2d1 (patch) | |
tree | b412be8108c7265f1d4a6e99c3dcbaea18ed2662 /kernel/dma/remap.c | |
parent | dma-mapping: support highmem in the generic remap allocator (diff) | |
download | linux-e440e26a0251b054243b3db6356f3869a9f9c2d1.tar.xz linux-e440e26a0251b054243b3db6356f3869a9f9c2d1.zip |
dma-remap: support DMA_ATTR_NO_KERNEL_MAPPING
Do not waste vmalloc space on allocations that do not require a mapping
into the kernel address space.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Diffstat (limited to 'kernel/dma/remap.c')
-rw-r--r-- | kernel/dma/remap.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c index dcc82dd668f8..68a64e3ff6a1 100644 --- a/kernel/dma/remap.c +++ b/kernel/dma/remap.c @@ -200,7 +200,8 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, size = PAGE_ALIGN(size); - if (!gfpflags_allow_blocking(flags)) { + if (!gfpflags_allow_blocking(flags) && + !(attrs & DMA_ATTR_NO_KERNEL_MAPPING)) { ret = dma_alloc_from_pool(size, &page, flags); if (!ret) return NULL; @@ -215,6 +216,9 @@ 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 */ + /* create a coherent mapping */ ret = dma_common_contiguous_remap(page, size, VM_USERMAP, arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs), @@ -227,7 +231,10 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, void arch_dma_free(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, unsigned long attrs) { - if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) { + if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) { + /* vaddr is a struct page cookie, not a kernel address */ + __dma_direct_free_pages(dev, size, vaddr); + } else if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) { phys_addr_t phys = dma_to_phys(dev, dma_handle); struct page *page = pfn_to_page(__phys_to_pfn(phys)); |