diff options
author | Zoltan Menyhart <Zoltan.Menyhart@bull.net> | 2008-04-11 18:21:35 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2008-04-11 18:21:35 -0400 |
commit | 98075d245a5bc4aeebc2e9f16fa8b089a5c200ac (patch) | |
tree | 5d248fa7ec872548e43ed2acb864d701adc65f42 | |
parent | c19b2930df0621500913c005c06978bd8933110b (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.c | 23 | ||||
-rw-r--r-- | arch/ia64/mm/contig.c | 2 | ||||
-rw-r--r-- | arch/ia64/mm/discontig.c | 2 | ||||
-rw-r--r-- | arch/ia64/mm/init.c | 6 | ||||
-rw-r--r-- | include/asm-ia64/meminit.h | 3 |
5 files changed, 29 insertions, 7 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 4aa9eaea76c3..c85b7dd6ef33 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 | */ | ||
183 | int __init | ||
184 | filter_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 | |||
179 | static void __init | 202 | static void __init |
180 | sort_regions (struct rsvd_region *rsvd_region, int max) | 203 | sort_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 0479661fa41a..798bf9835a51 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 ffee1ea00bb0..96d5fbfa44a4 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 da05893294b5..5c1de53c8c1c 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 | ||
549 | int __init | 549 | int __init |
550 | register_active_ranges(u64 start, u64 end, void *arg) | 550 | register_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 f93308f54b61..7245a5781594 100644 --- a/include/asm-ia64/meminit.h +++ b/include/asm-ia64/meminit.h | |||
@@ -35,6 +35,7 @@ extern void find_memory (void); | |||
35 | extern void reserve_memory (void); | 35 | extern void reserve_memory (void); |
36 | extern void find_initrd (void); | 36 | extern void find_initrd (void); |
37 | extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg); | 37 | extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg); |
38 | extern int filter_memory (unsigned long start, unsigned long end, void *arg); | ||
38 | extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e); | 39 | extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e); |
39 | extern int find_max_min_low_pfn (unsigned long , unsigned long, void *); | 40 | extern 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 | ||
59 | extern int register_active_ranges(u64 start, u64 end, void *arg); | 60 | extern 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 */ |