diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig index bfef21b4a9ae..c9fa0a922cba 100644 --- a/kernel/dma/Kconfig +++ b/kernel/dma/Kconfig @@ -181,6 +181,16 @@ config DMA_NUMA_CMA or set the node id and its size of CMA by specifying "numa_cma= :size[,:size]" on the kernel's command line. +config CMA_SIZE_PERNUMA + bool "Default CMA area per NUMA node" + depends on DMA_NUMA_CMA + default y + help + On systems with more than one NUMA node, the selected CMA + area size will be also allocated on each additional node, + so that most devices may have benefit from better DMA + locality without an explicit command-line opt-in. + comment "Default contiguous memory area size:" config CMA_SIZE_MBYTES diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index 03f52bd17120..799f6e9c88bd 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -136,6 +136,7 @@ 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; static int __init early_numa_cma(char *p) { @@ -164,6 +165,7 @@ static int __init early_numa_cma(char *p) break; } + numa_cma_configured = true; return 0; } early_param("numa_cma", early_numa_cma); @@ -171,6 +173,7 @@ early_param("numa_cma", early_numa_cma); static int __init early_cma_pernuma(char *p) { pernuma_size_bytes = memparse(p, &p); + numa_cma_configured = true; return 0; } early_param("cma_pernuma", early_cma_pernuma); @@ -199,6 +202,11 @@ static void __init dma_numa_cma_reserve(void) { int nid; + if (IS_ENABLED(CONFIG_CMA_SIZE_PERNUMA) && + !numa_cma_configured && dma_contiguous_default_area && + nr_online_nodes > 1) + pernuma_size_bytes = cma_get_size(dma_contiguous_default_area); + for_each_node(nid) { int ret; char name[CMA_MAX_NAME]; @@ -255,8 +263,6 @@ void __init dma_contiguous_reserve(phys_addr_t limit) phys_addr_t selected_limit = limit; bool fixed = false; - dma_numa_cma_reserve(); - pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); if (size_cmdline != -1) { @@ -312,6 +318,8 @@ void __init dma_contiguous_reserve(phys_addr_t limit) if (ret) pr_warn("Couldn't queue default CMA region for heap creation."); } + + dma_numa_cma_reserve(); } void __weak