dma-contiguous: simplify numa cma area handling

Currently, there are 2 kernel cmdline ways to setup numa cma area:
"cma_pernuma=" and "numa_cma=", and there are 2 cma arrays as well,
while they have no difference technically. Robin suggested to cleanup
the code and only use one array [1], as "the apparent intent that
users only want one _or_ the other".

Simplify the code by only using one array to save the numa cma area.
And in rare case that a user really setup the 2 cmdline parameters
at the same time,  let the per-node specific size setting 'numa_cma='
take priority over the global numa cma setting.

Link[1]: https://lore.kernel.org/lkml/43c5301c-fe6a-41e4-9482-ccfc7b62f2a7@arm.com/

Suggested-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Feng Tang <feng.tang@linux.alibaba.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20260525015111.6267-1-feng.tang@linux.alibaba.com
This commit is contained in:
Feng Tang
2026-05-25 09:51:11 +08:00
committed by Marek Szyprowski
parent 7e6ace2535
commit d5cae2261b
3 changed files with 19 additions and 35 deletions

View File

@@ -895,6 +895,10 @@ Kernel parameters
contiguous memory allocations. It will reserve CMA
area for the specified node.
If it is setup together with upper 'cmd_pernuma='
(unlikely), its size setting takes priority for the
specified numa nodes.
With numa CMA enabled, DMA users on node nid will
first try to allocate buffer from the numa area
which is located in node nid, if the allocation fails,

View File

@@ -179,7 +179,9 @@ config DMA_NUMA_CMA
You can set the size of pernuma CMA by specifying "cma_pernuma=size"
or set the node id and its size of CMA by specifying "numa_cma=
<node>:size[,<node>:size]" on the kernel's command line.
<node>:size[,<node>:size]" on the kernel's command line. And in
rare case that the above 2 are both setup, then the "numa_cma="
takes priority for the specified numa nodes.
config CMA_SIZE_PERNUMA
bool "Default CMA area per NUMA node"

View File

@@ -134,7 +134,6 @@ EXPORT_SYMBOL_GPL(dev_get_cma_area);
static struct cma *dma_contiguous_numa_area[MAX_NUMNODES];
static phys_addr_t numa_cma_size[MAX_NUMNODES] __initdata;
static struct cma *dma_contiguous_pernuma_area[MAX_NUMNODES];
static phys_addr_t pernuma_size_bytes __initdata;
static bool numa_cma_configured __initdata;
@@ -208,7 +207,7 @@ static void __init dma_numa_cma_reserve(void)
pernuma_size_bytes = cma_get_size(dma_contiguous_default_area);
for_each_node(nid) {
int ret;
int size, ret;
char name[CMA_MAX_NAME];
struct cma **cma;
@@ -218,27 +217,17 @@ static void __init dma_numa_cma_reserve(void)
continue;
}
if (pernuma_size_bytes) {
/* per-node numa setting has the priority */
size = numa_cma_size[nid] ?: pernuma_size_bytes;
if (!size)
continue;
cma = &dma_contiguous_pernuma_area[nid];
snprintf(name, sizeof(name), "pernuma%d", nid);
ret = cma_declare_contiguous_nid(0, pernuma_size_bytes, 0, 0,
0, false, name, cma, nid);
if (ret)
pr_warn("%s: reservation failed: err %d, node %d", __func__,
ret, nid);
}
if (numa_cma_size[nid]) {
cma = &dma_contiguous_numa_area[nid];
snprintf(name, sizeof(name), "numa%d", nid);
ret = cma_declare_contiguous_nid(0, numa_cma_size[nid], 0, 0, 0, false,
name, cma, nid);
if (ret)
pr_warn("%s: reservation failed: err %d, node %d", __func__,
ret, nid);
}
cma = &dma_contiguous_numa_area[nid];
snprintf(name, sizeof(name), "numa%d", nid);
ret = cma_declare_contiguous_nid(0, size, 0, 0, 0, false, name, cma, nid);
if (ret)
pr_warn("%s: reservation failed: err %d, node %d", __func__,
ret, nid);
}
}
#else
@@ -437,16 +426,8 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
#ifdef CONFIG_DMA_NUMA_CMA
if (nid != NUMA_NO_NODE && !(gfp & (GFP_DMA | GFP_DMA32))) {
struct cma *cma = dma_contiguous_pernuma_area[nid];
struct cma *cma = dma_contiguous_numa_area[nid];
struct page *page;
if (cma) {
page = cma_alloc_aligned(cma, size, gfp);
if (page)
return page;
}
cma = dma_contiguous_numa_area[nid];
if (cma) {
page = cma_alloc_aligned(cma, size, gfp);
if (page)
@@ -484,9 +465,6 @@ void dma_free_contiguous(struct device *dev, struct page *page, size_t size)
* otherwise, page is from either per-numa cma or default cma
*/
#ifdef CONFIG_DMA_NUMA_CMA
if (cma_release(dma_contiguous_pernuma_area[page_to_nid(page)],
page, count))
return;
if (cma_release(dma_contiguous_numa_area[page_to_nid(page)],
page, count))
return;