]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
of: reserved_mem: Allow reserved_mem framework detect "cma=" kernel param
authorOreoluwa Babatunde <oreoluwa.babatunde@oss.qualcomm.com>
Mon, 26 Jan 2026 17:13:27 +0000 (18:13 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Wed, 28 Jan 2026 23:26:36 +0000 (00:26 +0100)
When initializing the default cma region, the "cma=" kernel parameter
takes priority over a DT defined linux,cma-default region. Hence, give
the reserved_mem framework the ability to detect this so that the DT
defined cma region can skip initialization accordingly.

Signed-off-by: Oreoluwa Babatunde <oreoluwa.babatunde@oss.qualcomm.com>
Tested-by: Joy Zou <joy.zou@nxp.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Fixes: 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed")
Fixes: 2c223f7239f3 ("of: reserved_mem: Restructure call site for dma_contiguous_early_fixup()")
Link: https://lore.kernel.org/r/20251210002027.1171519-1-oreoluwa.babatunde@oss.qualcomm.com
[mszyprow: rebased onto v6.19-rc1, added fixes tags, added a stub for
 cma_skip_dt_default_reserved_mem() if no CONFIG_DMA_CMA is set]
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
drivers/of/of_reserved_mem.c
include/linux/cma.h
kernel/dma/contiguous.c

index 5619ec9178587123f93779184236009d2e9942ac..a2a13617c6f49ec7cd7accef897446f5eb6479a1 100644 (file)
@@ -157,13 +157,19 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
        phys_addr_t base, size;
        int i, len;
        const __be32 *prop;
-       bool nomap;
+       bool nomap, default_cma;
 
        prop = of_flat_dt_get_addr_size_prop(node, "reg", &len);
        if (!prop)
                return -ENOENT;
 
        nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
+       default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
+
+       if (default_cma && cma_skip_dt_default_reserved_mem()) {
+               pr_err("Skipping dt linux,cma-default for \"cma=\" kernel param.\n");
+               return -EINVAL;
+       }
 
        for (i = 0; i < len; i++) {
                u64 b, s;
@@ -248,10 +254,13 @@ void __init fdt_scan_reserved_mem_reg_nodes(void)
 
        fdt_for_each_subnode(child, fdt, node) {
                const char *uname;
+               bool default_cma = of_get_flat_dt_prop(child, "linux,cma-default", NULL);
                u64 b, s;
 
                if (!of_fdt_device_is_available(fdt, child))
                        continue;
+               if (default_cma && cma_skip_dt_default_reserved_mem())
+                       continue;
 
                if (!of_flat_dt_get_addr_size(child, "reg", &b, &s))
                        continue;
@@ -389,7 +398,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam
        phys_addr_t base = 0, align = 0, size;
        int i, len;
        const __be32 *prop;
-       bool nomap;
+       bool nomap, default_cma;
        int ret;
 
        prop = of_get_flat_dt_prop(node, "size", &len);
@@ -413,6 +422,12 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam
        }
 
        nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
+       default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
+
+       if (default_cma && cma_skip_dt_default_reserved_mem()) {
+               pr_err("Skipping dt linux,cma-default for \"cma=\" kernel param.\n");
+               return -EINVAL;
+       }
 
        /* Need adjust the alignment to satisfy the CMA requirement */
        if (IS_ENABLED(CONFIG_CMA)
index 62d9c1cf632652489ccd9e01bf1370f2b1f3c249..2e6931735880bdf34ad8eb425de770b07a2a6a70 100644 (file)
@@ -57,6 +57,15 @@ extern bool cma_intersects(struct cma *cma, unsigned long start, unsigned long e
 
 extern void cma_reserve_pages_on_error(struct cma *cma);
 
+#ifdef CONFIG_DMA_CMA
+extern bool cma_skip_dt_default_reserved_mem(void);
+#else
+static inline bool cma_skip_dt_default_reserved_mem(void)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_CMA
 struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp);
 bool cma_free_folio(struct cma *cma, const struct folio *folio);
index d8fd6f779f797f711b8e0fd628f868d644b8f784..0e266979728b217f56810268eb3e800f9fa6033a 100644 (file)
@@ -91,6 +91,16 @@ static int __init early_cma(char *p)
 }
 early_param("cma", early_cma);
 
+/*
+ * cma_skip_dt_default_reserved_mem - This is called from the
+ * reserved_mem framework to detect if the default cma region is being
+ * set by the "cma=" kernel parameter.
+ */
+bool __init cma_skip_dt_default_reserved_mem(void)
+{
+       return size_cmdline != -1;
+}
+
 #ifdef CONFIG_DMA_NUMA_CMA
 
 static struct cma *dma_contiguous_numa_area[MAX_NUMNODES];
@@ -470,12 +480,6 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        struct cma *cma;
        int err;
 
-       if (size_cmdline != -1 && default_cma) {
-               pr_info("Reserved memory: bypass %s node, using cmdline CMA params instead\n",
-                       rmem->name);
-               return -EBUSY;
-       }
-
        if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
            of_get_flat_dt_prop(node, "no-map", NULL))
                return -EINVAL;