From: Olof Johansson As discussed on the ppc64 list yesterday and today: On some ppc64 systems, Open Firmware will give memory device nodes that are only 16MB in size, instead of the 256MB that our NUMA code currently expects (see MEMORY_INCREMENT in mmzone.h). Just changing the defines from 256MB to 16MB makes the table blow up from 32KB to 512KB, so this patch also makes it dynamically allocated based on actual memory size. Since all this is done before (well, during) bootmem init so we need to use lmb_alloc(). Finally, there's no need to use a full int for node ID. Current max is 16 nodes, so a signed char still leaves plenty of room to grow. --- 25-akpm/arch/ppc64/mm/numa.c | 21 ++++++++++++++++++--- 25-akpm/include/asm-ppc64/mmzone.h | 6 +++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff -puN arch/ppc64/mm/numa.c~ppc64-NUMA-fix-for-16MB-LMBs arch/ppc64/mm/numa.c --- 25/arch/ppc64/mm/numa.c~ppc64-NUMA-fix-for-16MB-LMBs 2004-04-04 16:52:59.838627872 -0700 +++ 25-akpm/arch/ppc64/mm/numa.c 2004-04-04 16:52:59.844626960 -0700 @@ -16,6 +16,7 @@ #include #include #include +#include #if 1 #define dbg(args...) udbg_printf(args) @@ -31,9 +32,7 @@ int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = ARRAY_INITIALISER}; -int numa_memory_lookup_table[MAX_MEMORY >> MEMORY_INCREMENT_SHIFT] = - { [ 0 ... ((MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1)] = - ARRAY_INITIALISER}; +char *numa_memory_lookup_table; cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0}; @@ -65,12 +64,20 @@ static int __init parse_numa_properties( int *memory_associativity; int depth; int max_domain = 0; + long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; + long i; if (strstr(saved_command_line, "numa=off")) { printk(KERN_WARNING "NUMA disabled by user\n"); return -1; } + numa_memory_lookup_table = + (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); + + for (i = 0; i < entries ; i++) + numa_memory_lookup_table[i] = ARRAY_INITIALISER; + cpu = of_find_node_by_type(NULL, "cpu"); if (!cpu) goto err; @@ -232,6 +239,14 @@ static void __init setup_nonnuma(void) printk(KERN_INFO "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); + if (!numa_memory_lookup_table) { + long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT; + numa_memory_lookup_table = + (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); + for (i = 0; i < entries ; i++) + numa_memory_lookup_table[i] = ARRAY_INITIALISER; + } + for (i = 0; i < NR_CPUS; i++) map_cpu_to_node(i, 0); diff -puN include/asm-ppc64/mmzone.h~ppc64-NUMA-fix-for-16MB-LMBs include/asm-ppc64/mmzone.h --- 25/include/asm-ppc64/mmzone.h~ppc64-NUMA-fix-for-16MB-LMBs 2004-04-04 16:52:59.839627720 -0700 +++ 25-akpm/include/asm-ppc64/mmzone.h 2004-04-04 16:52:59.844626960 -0700 @@ -19,13 +19,13 @@ extern struct pglist_data node_data[]; */ extern int numa_cpu_lookup_table[]; -extern int numa_memory_lookup_table[]; +extern char *numa_memory_lookup_table; extern cpumask_t numa_cpumask_lookup_table[]; extern int nr_cpus_in_node[]; #define MAX_MEMORY (1UL << 41) -/* 256MB regions */ -#define MEMORY_INCREMENT_SHIFT 28 +/* 16MB regions */ +#define MEMORY_INCREMENT_SHIFT 24 #define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT) /* NUMA debugging, will not work on a DLPAR machine */ _