aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZoltan Menyhart <Zoltan.Menyhart@bull.net>2008-04-11 18:21:35 -0400
committerTony Luck <tony.luck@intel.com>2008-04-11 18:21:35 -0400
commit98075d245a5bc4aeebc2e9f16fa8b089a5c200ac (patch)
tree5d248fa7ec872548e43ed2acb864d701adc65f42
parentc19b2930df0621500913c005c06978bd8933110b (diff)
[IA64] Fix NUMA configuration issue
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>
-rw-r--r--arch/ia64/kernel/setup.c23
-rw-r--r--arch/ia64/mm/contig.c2
-rw-r--r--arch/ia64/mm/discontig.c2
-rw-r--r--arch/ia64/mm/init.c6
-rw-r--r--include/asm-ia64/meminit.h3
5 files changed, 29 insertions, 7 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 4aa9eaea76c..c85b7dd6ef3 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -176,6 +176,29 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
176 return 0; 176 return 0;
177} 177}
178 178
179/*
180 * Similar to "filter_rsvd_memory()", but the reserved memory ranges
181 * are not filtered out.
182 */
183int __init
184filter_memory(unsigned long start, unsigned long end, void *arg)
185{
186 void (*func)(unsigned long, unsigned long, int);
187
188#if IGNORE_PFN0
189 if (start == PAGE_OFFSET) {
190 printk(KERN_WARNING "warning: skipping physical page 0\n");
191 start += PAGE_SIZE;
192 if (start >= end)
193 return 0;
194 }
195#endif
196 func = arg;
197 if (start < end)
198 call_pernode_memory(__pa(start), end - start, func);
199 return 0;
200}
201
179static void __init 202static void __init
180sort_regions (struct rsvd_region *rsvd_region, int max) 203sort_regions (struct rsvd_region *rsvd_region, int max)
181{ 204{
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 0479661fa41..798bf9835a5 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -253,7 +253,7 @@ paging_init (void)
253 max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 253 max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
254 254
255#ifdef CONFIG_VIRTUAL_MEM_MAP 255#ifdef CONFIG_VIRTUAL_MEM_MAP
256 efi_memmap_walk(register_active_ranges, NULL); 256 efi_memmap_walk(filter_memory, register_active_ranges);
257 efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); 257 efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
258 if (max_gap < LARGE_GAP) { 258 if (max_gap < LARGE_GAP) {
259 vmem_map = (struct page *) 0; 259 vmem_map = (struct page *) 0;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index ffee1ea00bb..96d5fbfa44a 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -444,7 +444,7 @@ void __init find_memory(void)
444 mem_data[node].min_pfn = ~0UL; 444 mem_data[node].min_pfn = ~0UL;
445 } 445 }
446 446
447 efi_memmap_walk(register_active_ranges, NULL); 447 efi_memmap_walk(filter_memory, register_active_ranges);
448 448
449 /* 449 /*
450 * Initialize the boot memory maps in reverse order since that's 450 * Initialize the boot memory maps in reverse order since that's
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index da05893294b..5c1de53c8c1 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -547,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
547#endif /* CONFIG_VIRTUAL_MEM_MAP */ 547#endif /* CONFIG_VIRTUAL_MEM_MAP */
548 548
549int __init 549int __init
550register_active_ranges(u64 start, u64 end, void *arg) 550register_active_ranges(u64 start, u64 len, int nid)
551{ 551{
552 int nid = paddr_to_nid(__pa(start)); 552 u64 end = start + len;
553 553
554 if (nid < 0)
555 nid = 0;
556#ifdef CONFIG_KEXEC 554#ifdef CONFIG_KEXEC
557 if (start > crashk_res.start && start < crashk_res.end) 555 if (start > crashk_res.start && start < crashk_res.end)
558 start = crashk_res.end; 556 start = crashk_res.end;
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index f93308f54b6..7245a578159 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -35,6 +35,7 @@ extern void find_memory (void);
35extern void reserve_memory (void); 35extern void reserve_memory (void);
36extern void find_initrd (void); 36extern void find_initrd (void);
37extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg); 37extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
38extern int filter_memory (unsigned long start, unsigned long end, void *arg);
38extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e); 39extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
39extern int find_max_min_low_pfn (unsigned long , unsigned long, void *); 40extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
40 41
@@ -56,7 +57,7 @@ extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
56 57
57#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ 58#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
58 59
59extern int register_active_ranges(u64 start, u64 end, void *arg); 60extern int register_active_ranges(u64 start, u64 len, int nid);
60 61
61#ifdef CONFIG_VIRTUAL_MEM_MAP 62#ifdef CONFIG_VIRTUAL_MEM_MAP
62# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ 63# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */