diff options
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r-- | arch/x86/kernel/e820.c | 66 |
1 files changed, 27 insertions, 39 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 056e65d5012b..62d61e9976eb 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/acpi.h> | 19 | #include <linux/acpi.h> |
20 | #include <linux/firmware-map.h> | 20 | #include <linux/firmware-map.h> |
21 | #include <linux/memblock.h> | 21 | #include <linux/memblock.h> |
22 | #include <linux/sort.h> | ||
22 | 23 | ||
23 | #include <asm/e820.h> | 24 | #include <asm/e820.h> |
24 | #include <asm/proto.h> | 25 | #include <asm/proto.h> |
@@ -227,22 +228,38 @@ void __init e820_print_map(char *who) | |||
227 | * ____________________33__ | 228 | * ____________________33__ |
228 | * ______________________4_ | 229 | * ______________________4_ |
229 | */ | 230 | */ |
231 | struct change_member { | ||
232 | struct e820entry *pbios; /* pointer to original bios entry */ | ||
233 | unsigned long long addr; /* address for this change point */ | ||
234 | }; | ||
235 | |||
236 | static int __init cpcompare(const void *a, const void *b) | ||
237 | { | ||
238 | struct change_member * const *app = a, * const *bpp = b; | ||
239 | const struct change_member *ap = *app, *bp = *bpp; | ||
240 | |||
241 | /* | ||
242 | * Inputs are pointers to two elements of change_point[]. If their | ||
243 | * addresses are unequal, their difference dominates. If the addresses | ||
244 | * are equal, then consider one that represents the end of its region | ||
245 | * to be greater than one that does not. | ||
246 | */ | ||
247 | if (ap->addr != bp->addr) | ||
248 | return ap->addr > bp->addr ? 1 : -1; | ||
249 | |||
250 | return (ap->addr != ap->pbios->addr) - (bp->addr != bp->pbios->addr); | ||
251 | } | ||
230 | 252 | ||
231 | int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, | 253 | int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, |
232 | u32 *pnr_map) | 254 | u32 *pnr_map) |
233 | { | 255 | { |
234 | struct change_member { | ||
235 | struct e820entry *pbios; /* pointer to original bios entry */ | ||
236 | unsigned long long addr; /* address for this change point */ | ||
237 | }; | ||
238 | static struct change_member change_point_list[2*E820_X_MAX] __initdata; | 256 | static struct change_member change_point_list[2*E820_X_MAX] __initdata; |
239 | static struct change_member *change_point[2*E820_X_MAX] __initdata; | 257 | static struct change_member *change_point[2*E820_X_MAX] __initdata; |
240 | static struct e820entry *overlap_list[E820_X_MAX] __initdata; | 258 | static struct e820entry *overlap_list[E820_X_MAX] __initdata; |
241 | static struct e820entry new_bios[E820_X_MAX] __initdata; | 259 | static struct e820entry new_bios[E820_X_MAX] __initdata; |
242 | struct change_member *change_tmp; | ||
243 | unsigned long current_type, last_type; | 260 | unsigned long current_type, last_type; |
244 | unsigned long long last_addr; | 261 | unsigned long long last_addr; |
245 | int chgidx, still_changing; | 262 | int chgidx; |
246 | int overlap_entries; | 263 | int overlap_entries; |
247 | int new_bios_entry; | 264 | int new_bios_entry; |
248 | int old_nr, new_nr, chg_nr; | 265 | int old_nr, new_nr, chg_nr; |
@@ -279,35 +296,7 @@ int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, | |||
279 | chg_nr = chgidx; | 296 | chg_nr = chgidx; |
280 | 297 | ||
281 | /* sort change-point list by memory addresses (low -> high) */ | 298 | /* sort change-point list by memory addresses (low -> high) */ |
282 | still_changing = 1; | 299 | sort(change_point, chg_nr, sizeof *change_point, cpcompare, NULL); |
283 | while (still_changing) { | ||
284 | still_changing = 0; | ||
285 | for (i = 1; i < chg_nr; i++) { | ||
286 | unsigned long long curaddr, lastaddr; | ||
287 | unsigned long long curpbaddr, lastpbaddr; | ||
288 | |||
289 | curaddr = change_point[i]->addr; | ||
290 | lastaddr = change_point[i - 1]->addr; | ||
291 | curpbaddr = change_point[i]->pbios->addr; | ||
292 | lastpbaddr = change_point[i - 1]->pbios->addr; | ||
293 | |||
294 | /* | ||
295 | * swap entries, when: | ||
296 | * | ||
297 | * curaddr > lastaddr or | ||
298 | * curaddr == lastaddr and curaddr == curpbaddr and | ||
299 | * lastaddr != lastpbaddr | ||
300 | */ | ||
301 | if (curaddr < lastaddr || | ||
302 | (curaddr == lastaddr && curaddr == curpbaddr && | ||
303 | lastaddr != lastpbaddr)) { | ||
304 | change_tmp = change_point[i]; | ||
305 | change_point[i] = change_point[i-1]; | ||
306 | change_point[i-1] = change_tmp; | ||
307 | still_changing = 1; | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | 300 | ||
312 | /* create a new bios memory map, removing overlaps */ | 301 | /* create a new bios memory map, removing overlaps */ |
313 | overlap_entries = 0; /* number of entries in the overlap table */ | 302 | overlap_entries = 0; /* number of entries in the overlap table */ |
@@ -714,7 +703,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn) | |||
714 | } | 703 | } |
715 | #endif | 704 | #endif |
716 | 705 | ||
717 | #ifdef CONFIG_HIBERNATION | 706 | #ifdef CONFIG_ACPI |
718 | /** | 707 | /** |
719 | * Mark ACPI NVS memory region, so that we can save/restore it during | 708 | * Mark ACPI NVS memory region, so that we can save/restore it during |
720 | * hibernation and the subsequent resume. | 709 | * hibernation and the subsequent resume. |
@@ -727,7 +716,7 @@ static int __init e820_mark_nvs_memory(void) | |||
727 | struct e820entry *ei = &e820.map[i]; | 716 | struct e820entry *ei = &e820.map[i]; |
728 | 717 | ||
729 | if (ei->type == E820_NVS) | 718 | if (ei->type == E820_NVS) |
730 | suspend_nvs_register(ei->addr, ei->size); | 719 | acpi_nvs_register(ei->addr, ei->size); |
731 | } | 720 | } |
732 | 721 | ||
733 | return 0; | 722 | return 0; |
@@ -1072,7 +1061,7 @@ void __init memblock_x86_fill(void) | |||
1072 | * We are safe to enable resizing, beause memblock_x86_fill() | 1061 | * We are safe to enable resizing, beause memblock_x86_fill() |
1073 | * is rather later for x86 | 1062 | * is rather later for x86 |
1074 | */ | 1063 | */ |
1075 | memblock_can_resize = 1; | 1064 | memblock_allow_resize(); |
1076 | 1065 | ||
1077 | for (i = 0; i < e820.nr_map; i++) { | 1066 | for (i = 0; i < e820.nr_map; i++) { |
1078 | struct e820entry *ei = &e820.map[i]; | 1067 | struct e820entry *ei = &e820.map[i]; |
@@ -1087,7 +1076,6 @@ void __init memblock_x86_fill(void) | |||
1087 | memblock_add(ei->addr, ei->size); | 1076 | memblock_add(ei->addr, ei->size); |
1088 | } | 1077 | } |
1089 | 1078 | ||
1090 | memblock_analyze(); | ||
1091 | memblock_dump_all(); | 1079 | memblock_dump_all(); |
1092 | } | 1080 | } |
1093 | 1081 | ||