From nobody Wed Apr 1 13:44:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1847E30F803; Tue, 31 Mar 2026 10:00:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774951227; cv=none; b=u9Bfzi0KbIUVtgwZYv3N6Qsgbi273mAef2yEamW70UA6AmLzz3bd8blrdAGgTaD7HT30CsXYraVdQ0HDOt0ouS9vr7Ahg2X4o1+fJdOTAk59Ecjdud0aRAMyQYnNrTftexkuTOlm/hhWya2WxZ8kf9oT2/FSMf4cq9T5pqwSHGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774951227; c=relaxed/simple; bh=2RziEouTjtQzhvFU7nMRdzuP59YmynilgplJsjF6ais=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tshCz4R9QtJiUvNgw/jl2LJVr9KwQH0E/aegQ9hpRJ9+p9wAI6gus7IQG8o6GF4RlS7pUDvk7rvRA9jjjgVjAUYWTvQaX/QL5CPXH3gqeIrqd3KFJDdCshUWx5sCRBD0HmSVhmvdn7QMZaErBgI9vgo2qm7RSj5qI63O/H3brog= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KSo3fkb1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KSo3fkb1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 58671C2BCB1; Tue, 31 Mar 2026 10:00:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774951224; bh=2RziEouTjtQzhvFU7nMRdzuP59YmynilgplJsjF6ais=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KSo3fkb1PtQO8hBEs29qrPHni57waTli1pc16dvDGP+vruzJBqN1b/Mh3z2gbXY4b pLynpkymbHiKKFVCBpy3ReB0qBGpkKz3SdgJs/Z5Nvqw51SWTwsR+7U9rOA7CqAvKq 3p7+6dOMFrCx74lnn681dpIGoKxRac5Fgu35SxSCUbGcY1jluS/ORRA7Q/A4axey+Q dyJfE6Wy+10LeISxd2Ookz/wYd8yyj38bOM3lpdjooExi7ctWdqCIc9i9mxSOXQvHc U/Epv9rqd1WhzIiG6IIgc0rKuty0xmv8ycqx8pEnOvXHAInamKZsyHhXAXdzbimkzu zaDi7jI+kaXFQ== From: Maxime Ripard Date: Tue, 31 Mar 2026 12:00:10 +0200 Subject: [PATCH v4 1/8] dma: contiguous: Turn heap registration logic around Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260331-dma-buf-heaps-as-modules-v4-1-e18fda504419@kernel.org> References: <20260331-dma-buf-heaps-as-modules-v4-0-e18fda504419@kernel.org> In-Reply-To: <20260331-dma-buf-heaps-as-modules-v4-0-e18fda504419@kernel.org> To: Sumit Semwal , Benjamin Gaignard , Brian Starkey , John Stultz , "T.J. Mercier" , =?utf-8?q?Christian_K=C3=B6nig?= , Marek Szyprowski , Robin Murphy , Andrew Morton , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko Cc: Albert Esteve , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, iommu@lists.linux.dev, linux-mm@kvack.org, Maxime Ripard X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7747; i=mripard@kernel.org; h=from:subject:message-id; bh=2RziEouTjtQzhvFU7nMRdzuP59YmynilgplJsjF6ais=; b=owGbwMvMwCmsHn9OcpHtvjLG02pJDJmnZ+tdXmoVdl/5vPUvF1WllgixQGGdU26r9Q6cajC+7 pGo5MLXMZWFQZiTQVZMkeWJTNjp5e2LqxzsV/6AmcPKBDKEgYtTACZyiJWxTlf828uPbVLSm25/ KUw7ffPbI8kanqSHr15/z2SOEAhVzy6+dlsmQVfox95dW30u6ptlM9anXzkuncl0x2mu4sHTHN8 OPqyQP6NkIMtv/2GV8Ubtur95G6LKXpsWNqyKTJSdwy+vYQUA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D 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 --- drivers/dma-buf/heaps/cma_heap.c | 19 ++------------ include/linux/dma-buf/heaps/cma.h | 16 ------------ include/linux/dma-map-ops.h | 5 ++++ kernel/dma/contiguous.c | 55 +++++++++++++++++++++++++++++++++++= ---- 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_h= eap.c index bd3370b9a3f6d4e18885a1d0e8ba3f659b85ef47..33cac626da1198e3c4a1cdcd562= 223c1924b6ceb 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -12,11 +12,10 @@ =20 #define pr_fmt(fmt) "cma_heap: " fmt =20 #include #include -#include #include #include #include #include #include @@ -28,23 +27,10 @@ #include #include =20 #define DEFAULT_CMA_NAME "default_cma_region" =20 -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 >=3D ARRAY_SIZE(dma_areas)) - return -EINVAL; - - dma_areas[dma_areas_num++] =3D cma; - - return 0; -} - struct cma_heap { struct dma_heap *heap; struct cma *cma; }; =20 @@ -412,22 +398,21 @@ static int __init __add_cma_heap(struct cma *cma, con= st char *name) } =20 static int __init add_cma_heaps(void) { struct cma *default_cma =3D dev_get_cma_area(NULL); + struct cma *cma; unsigned int i; int ret; =20 if (default_cma) { ret =3D __add_cma_heap(default_cma, DEFAULT_CMA_NAME); if (ret) return ret; } =20 - for (i =3D 0; i < dma_areas_num; i++) { - struct cma *cma =3D dma_areas[i]; - + for (i =3D 0; (cma =3D dma_contiguous_get_area_by_idx(i)) !=3D NULL; i++)= { ret =3D __add_cma_heap(cma, cma_get_name(cma)); if (ret) { pr_warn("Failed to add CMA heap %s", cma_get_name(cma)); continue; } diff --git a/include/linux/dma-buf/heaps/cma.h b/include/linux/dma-buf/heap= s/cma.h deleted file mode 100644 index e751479e21e703e24a5f799b4a7fc8bd0df3c1c4..000000000000000000000000000= 0000000000000 --- a/include/linux/dma-buf/heaps/cma.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef DMA_BUF_HEAP_CMA_H_ -#define DMA_BUF_HEAP_CMA_H_ - -struct cma; - -#ifdef CONFIG_DMABUF_HEAPS_CMA -int dma_heap_cma_register_heap(struct cma *cma); -#else -static inline int dma_heap_cma_register_heap(struct cma *cma) -{ - return 0; -} -#endif // CONFIG_DMABUF_HEAPS_CMA - -#endif // DMA_BUF_HEAP_CMA_H_ diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index 60b63756df821d839436618f1fca2bfa3eabe075..c4c93c72ff6ff3ff5c59b716197= 0805422e9dccb 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -97,10 +97,11 @@ static inline struct cma *dev_get_cma_area(struct devic= e *dev) { if (dev && dev->cma_area) return dev->cma_area; return dma_contiguous_default_area; } +struct cma *dma_contiguous_get_area_by_idx(unsigned int idx); =20 void dma_contiguous_reserve(phys_addr_t addr_limit); int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, phys_addr_t limit, struct cma **res_cma, bool fixed); =20 @@ -115,10 +116,14 @@ void dma_contiguous_early_fixup(phys_addr_t base, uns= igned long size); #else /* CONFIG_DMA_CMA */ static inline struct cma *dev_get_cma_area(struct device *dev) { return NULL; } +static inline struct cma *dma_contiguous_get_area_by_idx(unsigned int idx) +{ + return NULL; +} static inline void dma_contiguous_reserve(phys_addr_t limit) { } static inline int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, phys_addr_t limit, struct cma **res_cma, diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index c56004d314dc2e436cddf3b20a4ee6ce8178bee4..afa9fd31304051d200cd4396dec= 26dd50becc375 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -40,21 +40,51 @@ #include =20 #include #include #include -#include #include #include #include =20 #ifdef CONFIG_CMA_SIZE_MBYTES #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES #else #define CMA_SIZE_MBYTES 0 #endif =20 +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 >=3D ARRAY_SIZE(dma_contiguous_areas)) + return -EINVAL; + + dma_contiguous_areas[dma_contiguous_areas_num++] =3D cma; + + return 0; +} + +/** + * dma_contiguous_get_area_by_idx() - Get contiguous area at given index + * @idx: index of the area we query + * + * Queries for the contiguous area located at index @idx. + * + * Returns: + * A pointer to the requested contiguous area, or NULL otherwise. + */ +struct cma *dma_contiguous_get_area_by_idx(unsigned int idx) +{ + if (idx >=3D dma_contiguous_areas_num) + return NULL; + + return dma_contiguous_areas[idx]; +} +EXPORT_SYMBOL_GPL(dma_contiguous_get_area_by_idx); + struct cma *dma_contiguous_default_area; =20 /* * Default global CMA area size can be defined in kernel's .config. * This is useful mainly for distro maintainers to create a kernel @@ -262,13 +292,28 @@ void __init dma_contiguous_reserve(phys_addr_t limit) &dma_contiguous_default_area, fixed); if (ret) return; =20 - ret =3D dma_heap_cma_register_heap(dma_contiguous_default_area); + /* + * We need to insert the new area in our list to avoid + * any inconsistencies between having the default area + * listed in the DT or not. + * + * The DT case is handled by rmem_cma_setup() and will + * always insert all its areas in our list. However, if + * it didn't run (because OF_RESERVED_MEM isn't set, or + * there's no DT region specified), then we don't have a + * default area yet, and no area in our list. + * + * This block creates the default area in such a case, + * but we also need to insert it in our list to avoid + * having a default area but an empty list. + */ + ret =3D dma_contiguous_insert_area(dma_contiguous_default_area); if (ret) - pr_warn("Couldn't register default CMA heap."); + pr_warn("Couldn't queue default CMA region for heap creation."); } } =20 void __weak dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) @@ -504,13 +549,13 @@ static int __init rmem_cma_setup(struct reserved_mem = *rmem) rmem->priv =3D cma; =20 pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n", &rmem->base, (unsigned long)rmem->size / SZ_1M); =20 - err =3D dma_heap_cma_register_heap(cma); + err =3D dma_contiguous_insert_area(cma); if (err) - pr_warn("Couldn't register CMA heap."); + pr_warn("Couldn't store CMA reserved area."); =20 return 0; } RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup); #endif --=20 2.53.0