From b6ccf10f7c6543e5811aab97356799ba9ddcd907 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 17 Jul 2026 15:49:32 +0530 Subject: [PATCH 1/3] FROMGIT: dma: contiguous: Turn heap registration logic around The CMA heap instantiation was initially developed by having the contiguous DMA code call into the CMA heap to create a new instance every time a reserved memory area is probed. Turning the CMA heap into a module would create a dependency of the kernel on a module, which doesn't work. Let's turn the logic around and do the opposite: store all the reserved memory CMA regions into the contiguous DMA code, and provide an iterator for the heap to use when it probes. Signed-off-by: Maxime Ripard Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20260331-dma-buf-heaps-as-modules-v4-1-e18fda504419@kernel.org --- include/linux/dma-map-ops.h | 6 ++++++ kernel/dma/contiguous.c | 41 +++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index 10882d00cb170..8147a39df0618 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -98,6 +98,7 @@ static inline void set_dma_ops(struct device *dev, #ifdef CONFIG_DMA_CMA extern struct cma *dma_contiguous_default_area; +struct cma *dma_contiguous_get_area_by_idx(unsigned int idx); static inline struct cma *dev_get_cma_area(struct device *dev) { @@ -156,6 +157,11 @@ static inline void dma_free_contiguous(struct device *dev, struct page *page, static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { } + +static inline struct cma *dma_contiguous_get_area_by_idx(unsigned int idx) +{ + return NULL; +} #endif /* CONFIG_DMA_CMA*/ #ifdef CONFIG_DMA_DECLARE_COHERENT diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index 9071c08650e3a..1ebcba769d3b4 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -53,6 +53,27 @@ #endif struct cma *dma_contiguous_default_area; +static struct cma *dma_contiguous_areas[MAX_CMA_AREAS]; +static unsigned int dma_contiguous_areas_num; + +static int dma_contiguous_insert_area(struct cma *cma) +{ + if (dma_contiguous_areas_num >= ARRAY_SIZE(dma_contiguous_areas)) + return -EINVAL; + + dma_contiguous_areas[dma_contiguous_areas_num++] = cma; + + return 0; +} + +struct cma *dma_contiguous_get_area_by_idx(unsigned int idx) +{ + if (idx >= dma_contiguous_areas_num) + return NULL; + + return dma_contiguous_areas[idx]; +} +EXPORT_SYMBOL_GPL(dma_contiguous_get_area_by_idx); /* * Default global CMA area size can be defined in kernel's .config. @@ -251,13 +272,21 @@ void __init dma_contiguous_reserve(phys_addr_t limit) } if (selected_size && !dma_contiguous_default_area) { + int ret; + pr_debug("%s: reserving %ld MiB for global area\n", __func__, (unsigned long)selected_size / SZ_1M); - dma_contiguous_reserve_area(selected_size, selected_base, - selected_limit, - &dma_contiguous_default_area, - fixed); + ret = dma_contiguous_reserve_area(selected_size, selected_base, + selected_limit, + &dma_contiguous_default_area, + fixed); + if (ret) + return; + + ret = dma_contiguous_insert_area(dma_contiguous_default_area); + if (ret) + pr_warn("Couldn't queue default CMA region for heap creation.\n"); } } @@ -497,6 +526,10 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n", &rmem->base, (unsigned long)rmem->size / SZ_1M); + err = dma_contiguous_insert_area(cma); + if (err) + pr_warn("Couldn't store CMA reserved area.\n"); + return 0; } RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup); From 5e85b50828b6f0e4fb8064c19d5130877d5a4677 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 17 Jul 2026 15:53:20 +0530 Subject: [PATCH 2/3] FROMGIT: dma-buf: heaps: cma: Create CMA heap for each CMA reserved region Aside from the main CMA region, it can be useful to allow userspace to allocate from the other CMA reserved regions. Indeed, those regions can have specific properties that can be useful to a specific us-case. For example, one of them platform I've been with has ECC enabled on the entire memory but for a specific region. Using that region to allocate framebuffers can be particular beneficial because enabling the ECC has a performance and memory footprint cost. Thus, exposing these regions as heaps user-space can allocate from and import wherever needed allows to cover that use-case. For now, only shared-dma-pools regions with the reusable property (ie, backed by CMA) are supported, but eventually we'll want to support other DMA pools types. Since we collected all the CMA regions created during boot, we can simply iterate over all of them to create the heaps. This has a weird interaction with the recent work on the CMA name, in particular the backward compatibility code created by commit 854acbe75ff4 ("dma-buf: heaps: Give default CMA heap a fixed name"). Indeed, the old name was either 'reserved', or the name of the reserved-memory region device tree node if the linux,cma-default property was set. In both these cases, we have now collected this region during boot, and we're using the same name. So we're now largely redundant with the code to handle backward compatibility code, and we can thus remove it and the associated Kconfig option. Reviewed-by: T.J. Mercier Signed-off-by: Maxime Ripard Signed-off-by: Sumit Semwal Link: https://lore.kernel.org/r/20251013-dma-buf-ecc-heap-v8-5-04ce150ea3d9@kernel.org --- drivers/dma-buf/heaps/cma_heap.c | 46 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 0df0071119754..c9463a6d82a33 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -395,33 +395,45 @@ 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; + struct cma *cma; + unsigned int i; int ret; - if (!default_cma) - return 0; - - ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME); - if (ret) - return ret; - - 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; + if (default_cma) { + ret = __add_cma_heap(default_cma, DEFAULT_CMA_NAME); + if (ret) + return ret; + + 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"); + goto add_additional_heaps; + } + + ret = __add_cma_heap(default_cma, legacy_cma_name); + if (ret) + pr_warn("failed to add legacy heap: %pe\n", + ERR_PTR(ret)); } + } + +add_additional_heaps: + for (i = 0; (cma = dma_contiguous_get_area_by_idx(i)) != NULL; i++) { + if (cma == default_cma) + continue; - ret = __add_cma_heap(default_cma, legacy_cma_name); + ret = __add_cma_heap(cma, cma_get_name(cma)); if (ret) - pr_warn("failed to add legacy heap: %pe\n", - ERR_PTR(ret)); + pr_warn("failed to add CMA heap %s: %pe\n", + cma_get_name(cma), ERR_PTR(ret)); } return 0; } -module_init(add_default_cma_heap); +module_init(add_cma_heaps); MODULE_DESCRIPTION("DMA-BUF CMA Heap"); From fc8e99c6599a7aa1beaee6578c67a0538e917adb Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Fri, 17 Jul 2026 15:58:46 +0530 Subject: [PATCH 3/3] QCLINUX: qcom.config: Enable DMA_CMA for DMA-BUF heap support Enable CONFIG_DMA_CMA as a dependency to allow the DMA-BUF heap configs (DMABUF_HEAPS, DMABUF_HEAPS_CMA, DMABUF_HEAPS_SYSTEM) to be selected in qcom.config. Link: https://github.com/qualcomm-linux/kernel-topics/pull/1452 Signed-off-by: Bibek Kumar Patro --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 70af068f10e02..79094d39d6da0 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -24,6 +24,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_BTF_MODULES=y # CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set +CONFIG_DMA_CMA=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y