diff options
Diffstat (limited to 'drivers/dma-buf/heaps')
| -rw-r--r-- | drivers/dma-buf/heaps/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/dma-buf/heaps/cma_heap.c | 47 | ||||
| -rw-r--r-- | drivers/dma-buf/heaps/system_heap.c | 33 |
3 files changed, 54 insertions, 36 deletions
diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig index bb369b38b001..a5eef06c4226 100644 --- a/drivers/dma-buf/heaps/Kconfig +++ b/drivers/dma-buf/heaps/Kconfig @@ -12,13 +12,3 @@ config DMABUF_HEAPS_CMA Choose this option to enable dma-buf CMA heap. This heap is backed by the Contiguous Memory Allocator (CMA). If your system has these regions, you should say Y here. - -config DMABUF_HEAPS_CMA_LEGACY - bool "Legacy DMA-BUF CMA Heap" - default y - depends on DMABUF_HEAPS_CMA - help - Add a duplicate CMA-backed dma-buf heap with legacy naming derived - from the CMA area's devicetree node, or "reserved" if the area is not - defined in the devicetree. This uses the same underlying allocator as - CONFIG_DMABUF_HEAPS_CMA. diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 0df007111975..42f88193eab9 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -14,6 +14,7 @@ #include <linux/cma.h> #include <linux/dma-buf.h> +#include <linux/dma-buf/heaps/cma.h> #include <linux/dma-heap.h> #include <linux/dma-map-ops.h> #include <linux/err.h> @@ -21,12 +22,27 @@ #include <linux/io.h> #include <linux/mm.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_reserved_mem.h> #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/vmalloc.h> #define DEFAULT_CMA_NAME "default_cma_region" +static struct cma *dma_areas[MAX_CMA_AREAS] __initdata; +static unsigned int dma_areas_num __initdata; + +int __init dma_heap_cma_register_heap(struct cma *cma) +{ + if (dma_areas_num >= ARRAY_SIZE(dma_areas)) + return -EINVAL; + + dma_areas[dma_areas_num++] = cma; + + return 0; +} + struct cma_heap { struct dma_heap *heap; struct cma *cma; @@ -395,33 +411,30 @@ static int __init __add_cma_heap(struct cma *cma, const char *name) return 0; } -static int __init add_default_cma_heap(void) +static int __init add_cma_heaps(void) { struct cma *default_cma = dev_get_cma_area(NULL); - const char *legacy_cma_name; + unsigned int i; int ret; - if (!default_cma) - return 0; + if (default_cma) { + ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME); + if (ret) + return ret; + } - ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME); - if (ret) - return ret; + for (i = 0; i < dma_areas_num; i++) { + struct cma *cma = dma_areas[i]; - if (IS_ENABLED(CONFIG_DMABUF_HEAPS_CMA_LEGACY)) { - legacy_cma_name = cma_get_name(default_cma); - if (!strcmp(legacy_cma_name, DEFAULT_CMA_NAME)) { - pr_warn("legacy name and default name are the same, skipping legacy heap\n"); - return 0; + ret = __add_cma_heap(cma, cma_get_name(cma)); + if (ret) { + pr_warn("Failed to add CMA heap %s", cma_get_name(cma)); + continue; } - ret = __add_cma_heap(default_cma, legacy_cma_name); - if (ret) - pr_warn("failed to add legacy heap: %pe\n", - ERR_PTR(ret)); } return 0; } -module_init(add_default_cma_heap); +module_init(add_cma_heaps); MODULE_DESCRIPTION("DMA-BUF CMA Heap"); diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index bbe7881f1360..4c782fe33fd4 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -186,20 +186,35 @@ static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) struct system_heap_buffer *buffer = dmabuf->priv; struct sg_table *table = &buffer->sg_table; unsigned long addr = vma->vm_start; - struct sg_page_iter piter; - int ret; + unsigned long pgoff = vma->vm_pgoff; + struct scatterlist *sg; + int i, ret; + + for_each_sgtable_sg(table, sg, i) { + unsigned long n = sg->length >> PAGE_SHIFT; - for_each_sgtable_page(table, &piter, vma->vm_pgoff) { - struct page *page = sg_page_iter_page(&piter); + if (pgoff < n) + break; + pgoff -= n; + } + + for (; sg && addr < vma->vm_end; sg = sg_next(sg)) { + unsigned long n = (sg->length >> PAGE_SHIFT) - pgoff; + struct page *page = sg_page(sg) + pgoff; + unsigned long size = n << PAGE_SHIFT; + + if (addr + size > vma->vm_end) + size = vma->vm_end - addr; - ret = remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, - vma->vm_page_prot); + ret = remap_pfn_range(vma, addr, page_to_pfn(page), + size, vma->vm_page_prot); if (ret) return ret; - addr += PAGE_SIZE; - if (addr >= vma->vm_end) - return 0; + + addr += size; + pgoff = 0; } + return 0; } |
