aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/bootmem.c1
-rw-r--r--mm/memory_hotplug.c99
-rw-r--r--mm/sparse.c3
3 files changed, 100 insertions, 3 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index b6791646143e..369624d2789c 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -461,6 +461,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
461 461
462unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) 462unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
463{ 463{
464 register_page_bootmem_info_node(pgdat);
464 return free_all_bootmem_core(pgdat); 465 return free_all_bootmem_core(pgdat);
465} 466}
466 467
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c8b3ca79de2d..cba36ef0d506 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -58,8 +58,105 @@ static void release_memory_resource(struct resource *res)
58 return; 58 return;
59} 59}
60 60
61
62#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE 61#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
62#ifndef CONFIG_SPARSEMEM_VMEMMAP
63static void get_page_bootmem(unsigned long info, struct page *page, int magic)
64{
65 atomic_set(&page->_mapcount, magic);
66 SetPagePrivate(page);
67 set_page_private(page, info);
68 atomic_inc(&page->_count);
69}
70
71void put_page_bootmem(struct page *page)
72{
73 int magic;
74
75 magic = atomic_read(&page->_mapcount);
76 BUG_ON(magic >= -1);
77
78 if (atomic_dec_return(&page->_count) == 1) {
79 ClearPagePrivate(page);
80 set_page_private(page, 0);
81 reset_page_mapcount(page);
82 __free_pages_bootmem(page, 0);
83 }
84
85}
86
87void register_page_bootmem_info_section(unsigned long start_pfn)
88{
89 unsigned long *usemap, mapsize, section_nr, i;
90 struct mem_section *ms;
91 struct page *page, *memmap;
92
93 if (!pfn_valid(start_pfn))
94 return;
95
96 section_nr = pfn_to_section_nr(start_pfn);
97 ms = __nr_to_section(section_nr);
98
99 /* Get section's memmap address */
100 memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
101
102 /*
103 * Get page for the memmap's phys address
104 * XXX: need more consideration for sparse_vmemmap...
105 */
106 page = virt_to_page(memmap);
107 mapsize = sizeof(struct page) * PAGES_PER_SECTION;
108 mapsize = PAGE_ALIGN(mapsize) >> PAGE_SHIFT;
109
110 /* remember memmap's page */
111 for (i = 0; i < mapsize; i++, page++)
112 get_page_bootmem(section_nr, page, SECTION_INFO);
113
114 usemap = __nr_to_section(section_nr)->pageblock_flags;
115 page = virt_to_page(usemap);
116
117 mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
118
119 for (i = 0; i < mapsize; i++, page++)
120 get_page_bootmem(section_nr, page, MIX_INFO);
121
122}
123
124void register_page_bootmem_info_node(struct pglist_data *pgdat)
125{
126 unsigned long i, pfn, end_pfn, nr_pages;
127 int node = pgdat->node_id;
128 struct page *page;
129 struct zone *zone;
130
131 nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT;
132 page = virt_to_page(pgdat);
133
134 for (i = 0; i < nr_pages; i++, page++)
135 get_page_bootmem(node, page, NODE_INFO);
136
137 zone = &pgdat->node_zones[0];
138 for (; zone < pgdat->node_zones + MAX_NR_ZONES - 1; zone++) {
139 if (zone->wait_table) {
140 nr_pages = zone->wait_table_hash_nr_entries
141 * sizeof(wait_queue_head_t);
142 nr_pages = PAGE_ALIGN(nr_pages) >> PAGE_SHIFT;
143 page = virt_to_page(zone->wait_table);
144
145 for (i = 0; i < nr_pages; i++, page++)
146 get_page_bootmem(node, page, NODE_INFO);
147 }
148 }
149
150 pfn = pgdat->node_start_pfn;
151 end_pfn = pfn + pgdat->node_spanned_pages;
152
153 /* register_section info */
154 for (; pfn < end_pfn; pfn += PAGES_PER_SECTION)
155 register_page_bootmem_info_section(pfn);
156
157}
158#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
159
63static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) 160static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
64{ 161{
65 struct pglist_data *pgdat = zone->zone_pgdat; 162 struct pglist_data *pgdat = zone->zone_pgdat;
diff --git a/mm/sparse.c b/mm/sparse.c
index 186a85bf7912..8903c484389a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -210,7 +210,6 @@ static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long p
210/* 210/*
211 * Decode mem_map from the coded memmap 211 * Decode mem_map from the coded memmap
212 */ 212 */
213static
214struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum) 213struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
215{ 214{
216 /* mask off the extra low bits of information */ 215 /* mask off the extra low bits of information */
@@ -233,7 +232,7 @@ static int __meminit sparse_init_one_section(struct mem_section *ms,
233 return 1; 232 return 1;
234} 233}
235 234
236static unsigned long usemap_size(void) 235unsigned long usemap_size(void)
237{ 236{
238 unsigned long size_bytes; 237 unsigned long size_bytes;
239 size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8; 238 size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8;