]> err.no Git - linux-2.6/commitdiff
[IA64] Fix NUMA configuration issue
authorZoltan Menyhart <Zoltan.Menyhart@bull.net>
Fri, 11 Apr 2008 22:21:35 +0000 (15:21 -0700)
committerTony Luck <tony.luck@intel.com>
Fri, 11 Apr 2008 22:21:35 +0000 (15:21 -0700)
There is a NUMA memory configuration issue in 2.6.24:

A 2-node machine of ours has got the following memory layout:

Node 0: 0 - 2 Gbytes
Node 0: 4 - 8 Gbytes
Node 1: 8 - 16 Gbytes
Node 0: 16 - 18 Gbytes

"efi_memmap_init()" merges the three last ranges into one.

"register_active_ranges()" is called as follows:

efi_memmap_walk(register_active_ranges, NULL);

i.e. once for the 4 - 18 Gbytes range. It picks up the node
number from the start address, and registers all the memory for
the node #0.

"register_active_ranges()" should be called as follows to
make sure there is no merged address range at its entry:

efi_memmap_walk(filter_memory, register_active_ranges);

"filter_memory()" is similar to "filter_rsvd_memory()",
but the reserved memory ranges are not filtered out.

Signed-off-by: Zoltan Menyhart <Zoltan.Menyhart@bull.net>
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/kernel/setup.c
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
include/asm-ia64/meminit.h

index 4aa9eaea76c373bcab89dfa1d058984272030456..c85b7dd6ef338d408f785beeb27166d35a040ac2 100644 (file)
@@ -176,6 +176,29 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
        return 0;
 }
 
+/*
+ * Similar to "filter_rsvd_memory()", but the reserved memory ranges
+ * are not filtered out.
+ */
+int __init
+filter_memory(unsigned long start, unsigned long end, void *arg)
+{
+       void (*func)(unsigned long, unsigned long, int);
+
+#if IGNORE_PFN0
+       if (start == PAGE_OFFSET) {
+               printk(KERN_WARNING "warning: skipping physical page 0\n");
+               start += PAGE_SIZE;
+               if (start >= end)
+                       return 0;
+       }
+#endif
+       func = arg;
+       if (start < end)
+               call_pernode_memory(__pa(start), end - start, func);
+       return 0;
+}
+
 static void __init
 sort_regions (struct rsvd_region *rsvd_region, int max)
 {
index 0479661fa41aa0b94e04e163b14746f129ffee24..798bf9835a519f9ab20c748b6d5056ec69489a66 100644 (file)
@@ -253,7 +253,7 @@ paging_init (void)
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-       efi_memmap_walk(register_active_ranges, NULL);
+       efi_memmap_walk(filter_memory, register_active_ranges);
        efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
        if (max_gap < LARGE_GAP) {
                vmem_map = (struct page *) 0;
index ffee1ea00bb0c830fb192837811012c6133b8e4b..96d5fbfa44a4b201dbb4c101ae422aa3263c0908 100644 (file)
@@ -444,7 +444,7 @@ void __init find_memory(void)
                        mem_data[node].min_pfn = ~0UL;
                }
 
-       efi_memmap_walk(register_active_ranges, NULL);
+       efi_memmap_walk(filter_memory, register_active_ranges);
 
        /*
         * Initialize the boot memory maps in reverse order since that's
index da05893294b5b0930acf202f1f616f8a3b7e5f07..5c1de53c8c1c07e02aa4add71f749aa3dd6458f2 100644 (file)
@@ -547,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
 #endif /* CONFIG_VIRTUAL_MEM_MAP */
 
 int __init
-register_active_ranges(u64 start, u64 end, void *arg)
+register_active_ranges(u64 start, u64 len, int nid)
 {
-       int nid = paddr_to_nid(__pa(start));
+       u64 end = start + len;
 
-       if (nid < 0)
-               nid = 0;
 #ifdef CONFIG_KEXEC
        if (start > crashk_res.start && start < crashk_res.end)
                start = crashk_res.end;
index f93308f54b615ea673a669db653beca9c18c4ae6..7245a5781594932ee6a8b3d7cab5b1c3ec25939f 100644 (file)
@@ -35,6 +35,7 @@ extern void find_memory (void);
 extern void reserve_memory (void);
 extern void find_initrd (void);
 extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
+extern int filter_memory (unsigned long start, unsigned long end, void *arg);
 extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
 extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
 
@@ -56,7 +57,7 @@ extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
 
 #define IGNORE_PFN0    1       /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
 
-extern int register_active_ranges(u64 start, u64 end, void *arg);
+extern int register_active_ranges(u64 start, u64 len, int nid);
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 # define LARGE_GAP     0x40000000 /* Use virtual mem map if hole is > than this */