diff options
author | Andi Kleen <ak@suse.de> | 2006-05-15 12:19:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-16 10:59:31 -0400 |
commit | fad7906d16e8c4926aeb5b0f1756eb9f55b2837d (patch) | |
tree | 1a238328b29316e3aa8d8fa9f05dedcf1d58c153 | |
parent | 5491d0f3e206beb95eeb506510d62a1dab462df1 (diff) |
[PATCH] x86_64: Fix memory hotadd heuristics
This fixes some boot failures on Dell and Unisys systems with memory
hotadd added.
- Set hotadd_percent to 0 by default. This means anybody using hotadd
memory needs to specify the value on the command line. That's
because there are lots of Intel boxes which have a bogus hotplug area
in their SRAT and they would waste a lot of memory before.
- Fix calculation of how much memory to use when the hotplug area
exceeds hotadd_percent
- Fix fallback when the
- Fix fallback if memory hotadd is not compiled in.
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/x86_64/mm/srat.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 15ae9fcd65a7..e1513532df29 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -34,7 +34,10 @@ static nodemask_t nodes_found __initdata; | |||
34 | static struct bootnode nodes[MAX_NUMNODES] __initdata; | 34 | static struct bootnode nodes[MAX_NUMNODES] __initdata; |
35 | static struct bootnode nodes_add[MAX_NUMNODES] __initdata; | 35 | static struct bootnode nodes_add[MAX_NUMNODES] __initdata; |
36 | static int found_add_area __initdata; | 36 | static int found_add_area __initdata; |
37 | int hotadd_percent __initdata = 10; | 37 | int hotadd_percent __initdata = 0; |
38 | #ifndef RESERVE_HOTADD | ||
39 | #define hotadd_percent 0 /* Ignore all settings */ | ||
40 | #endif | ||
38 | static u8 pxm2node[256] = { [0 ... 255] = 0xff }; | 41 | static u8 pxm2node[256] = { [0 ... 255] = 0xff }; |
39 | 42 | ||
40 | /* Too small nodes confuse the VM badly. Usually they result | 43 | /* Too small nodes confuse the VM badly. Usually they result |
@@ -103,6 +106,7 @@ static __init void bad_srat(void) | |||
103 | int i; | 106 | int i; |
104 | printk(KERN_ERR "SRAT: SRAT not used.\n"); | 107 | printk(KERN_ERR "SRAT: SRAT not used.\n"); |
105 | acpi_numa = -1; | 108 | acpi_numa = -1; |
109 | found_add_area = 0; | ||
106 | for (i = 0; i < MAX_LOCAL_APIC; i++) | 110 | for (i = 0; i < MAX_LOCAL_APIC; i++) |
107 | apicid_to_node[i] = NUMA_NO_NODE; | 111 | apicid_to_node[i] = NUMA_NO_NODE; |
108 | for (i = 0; i < MAX_NUMNODES; i++) | 112 | for (i = 0; i < MAX_NUMNODES; i++) |
@@ -154,7 +158,8 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) | |||
154 | int pxm, node; | 158 | int pxm, node; |
155 | if (srat_disabled()) | 159 | if (srat_disabled()) |
156 | return; | 160 | return; |
157 | if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { bad_srat(); | 161 | if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { |
162 | bad_srat(); | ||
158 | return; | 163 | return; |
159 | } | 164 | } |
160 | if (pa->flags.enabled == 0) | 165 | if (pa->flags.enabled == 0) |
@@ -191,15 +196,17 @@ static int hotadd_enough_memory(struct bootnode *nd) | |||
191 | allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE; | 196 | allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE; |
192 | allowed = (allowed / 100) * hotadd_percent; | 197 | allowed = (allowed / 100) * hotadd_percent; |
193 | if (allocated + mem > allowed) { | 198 | if (allocated + mem > allowed) { |
199 | unsigned long range; | ||
194 | /* Give them at least part of their hotadd memory upto hotadd_percent | 200 | /* Give them at least part of their hotadd memory upto hotadd_percent |
195 | It would be better to spread the limit out | 201 | It would be better to spread the limit out |
196 | over multiple hotplug areas, but that is too complicated | 202 | over multiple hotplug areas, but that is too complicated |
197 | right now */ | 203 | right now */ |
198 | if (allocated >= allowed) | 204 | if (allocated >= allowed) |
199 | return 0; | 205 | return 0; |
200 | pages = (allowed - allocated + mem) / sizeof(struct page); | 206 | range = allowed - allocated; |
207 | pages = (range / PAGE_SIZE); | ||
201 | mem = pages * sizeof(struct page); | 208 | mem = pages * sizeof(struct page); |
202 | nd->end = nd->start + pages*PAGE_SIZE; | 209 | nd->end = nd->start + range; |
203 | } | 210 | } |
204 | /* Not completely fool proof, but a good sanity check */ | 211 | /* Not completely fool proof, but a good sanity check */ |
205 | addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem); | 212 | addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem); |