diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 48 |
1 files changed, 3 insertions, 45 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 855e0fc928b3..2e916c308ae6 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -24,28 +24,6 @@ | |||
24 | 24 | ||
25 | #include <asm/tlbflush.h> | 25 | #include <asm/tlbflush.h> |
26 | 26 | ||
27 | static struct page *__kmalloc_section_memmap(unsigned long nr_pages) | ||
28 | { | ||
29 | struct page *page, *ret; | ||
30 | unsigned long memmap_size = sizeof(struct page) * nr_pages; | ||
31 | |||
32 | page = alloc_pages(GFP_KERNEL, get_order(memmap_size)); | ||
33 | if (page) | ||
34 | goto got_map_page; | ||
35 | |||
36 | ret = vmalloc(memmap_size); | ||
37 | if (ret) | ||
38 | goto got_map_ptr; | ||
39 | |||
40 | return NULL; | ||
41 | got_map_page: | ||
42 | ret = (struct page *)pfn_to_kaddr(page_to_pfn(page)); | ||
43 | got_map_ptr: | ||
44 | memset(ret, 0, memmap_size); | ||
45 | |||
46 | return ret; | ||
47 | } | ||
48 | |||
49 | extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, | 27 | extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, |
50 | unsigned long size); | 28 | unsigned long size); |
51 | static void __add_zone(struct zone *zone, unsigned long phys_start_pfn) | 29 | static void __add_zone(struct zone *zone, unsigned long phys_start_pfn) |
@@ -60,35 +38,15 @@ static void __add_zone(struct zone *zone, unsigned long phys_start_pfn) | |||
60 | zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages); | 38 | zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages); |
61 | } | 39 | } |
62 | 40 | ||
63 | extern int sparse_add_one_section(struct zone *, unsigned long, | 41 | extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, |
64 | struct page *mem_map); | 42 | int nr_pages); |
65 | static int __add_section(struct zone *zone, unsigned long phys_start_pfn) | 43 | static int __add_section(struct zone *zone, unsigned long phys_start_pfn) |
66 | { | 44 | { |
67 | struct pglist_data *pgdat = zone->zone_pgdat; | 45 | struct pglist_data *pgdat = zone->zone_pgdat; |
68 | int nr_pages = PAGES_PER_SECTION; | 46 | int nr_pages = PAGES_PER_SECTION; |
69 | struct page *memmap; | ||
70 | int ret; | 47 | int ret; |
71 | 48 | ||
72 | /* | 49 | ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); |
73 | * This can potentially allocate memory, and does its own | ||
74 | * internal locking. | ||
75 | */ | ||
76 | sparse_index_init(pfn_to_section_nr(phys_start_pfn), pgdat->node_id); | ||
77 | |||
78 | pgdat_resize_lock(pgdat, &flags); | ||
79 | memmap = __kmalloc_section_memmap(nr_pages); | ||
80 | ret = sparse_add_one_section(zone, phys_start_pfn, memmap); | ||
81 | pgdat_resize_unlock(pgdat, &flags); | ||
82 | |||
83 | if (ret <= 0) { | ||
84 | /* the mem_map didn't get used */ | ||
85 | if (memmap >= (struct page *)VMALLOC_START && | ||
86 | memmap < (struct page *)VMALLOC_END) | ||
87 | vfree(memmap); | ||
88 | else | ||
89 | free_pages((unsigned long)memmap, | ||
90 | get_order(sizeof(struct page) * nr_pages)); | ||
91 | } | ||
92 | 50 | ||
93 | if (ret < 0) | 51 | if (ret < 0) |
94 | return ret; | 52 | return ret; |