Certain devices can possess non-standard memory capacities, not constrained to multiples of 1GB. Provide a kernel parameter so that we can map the device memory completely on memory hotplug.
Restrict memory_block_size value to a power of 2 value similar to LMB size. The memory block size should also be more than the section size. Reviewed-by: Reza Arbab <ar...@linux.ibm.com> Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com> --- .../admin-guide/kernel-parameters.txt | 3 +++ arch/powerpc/kernel/setup_64.c | 23 +++++++++++++++++++ arch/powerpc/mm/init_64.c | 17 ++++++++++---- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index a1457995fd41..4e49696e0976 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3201,6 +3201,9 @@ Note that even when enabled, there are a few cases where the feature is not effective. + memory_block_size=size [PPC] + Use this parameter to configure the memory block size value. + memtest= [KNL,X86,ARM,M68K,PPC,RISCV] Enable memtest Format: <integer> default : 0 <disable> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 246201d0d879..cbdb924462c7 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -892,6 +892,29 @@ unsigned long memory_block_size_bytes(void) return MIN_MEMORY_BLOCK_SIZE; } + +/* + * Restrict to a power of 2 value for memblock which is larger than + * section size + */ +static int __init parse_mem_block_size(char *ptr) +{ + unsigned int order; + unsigned long size = memparse(ptr, NULL); + + order = fls64(size); + if (!order) + return 0; + + order--; + if (order < SECTION_SIZE_BITS) + return 0; + + memory_block_size = 1UL << order; + + return 0; +} +early_param("memory_block_size", parse_mem_block_size); #endif #if defined(CONFIG_PPC_INDIRECT_PIO) || defined(CONFIG_PPC_INDIRECT_MMIO) diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index d74d4a441616..fcda46c2b8df 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -566,13 +566,20 @@ static int __init probe_memory_block_size(unsigned long node, const char *uname, return 0; } -/* - * start with 1G memory block size. Early init will - * fix this with correct value. - */ -unsigned long memory_block_size __ro_after_init = 1UL << 30; +unsigned long memory_block_size __ro_after_init; static void __init early_init_memory_block_size(void) { + /* + * if it is set via early param just return. + */ + if (memory_block_size) + return; + + /* + * start with 1G memory block size. update_memory_block_size() + * will derive the right value based on device tree details. + */ + memory_block_size = SZ_1G; /* * We need to do memory_block_size probe early so that * radix__early_init_mmu() can use this as limit for -- 2.41.0