aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-10-01 11:58:32 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-10-01 12:24:04 -0400
commitb7a69ac303cbfc8d6fa8e91d10e8049244ba6847 (patch)
tree158deb4f96730bb7850ef50dc81dc1df7683439f /arch/arm/mm
parentd2a38ef9c1585b47462c7be5501228ac57fbd3b1 (diff)
[ARM] mm: finish ARM sparsemem support
... including some comments about the ordering required to bring sparsemem up. You have to repeatedly guess, test, reguess, try again and again to work out what the right ordering is. Many hours later... Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/init.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 9b7f0bf26f57..82c4b4217989 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -79,7 +79,7 @@ void show_mem(void)
79 show_free_areas(); 79 show_free_areas();
80 for_each_online_node(node) { 80 for_each_online_node(node) {
81 pg_data_t *n = NODE_DATA(node); 81 pg_data_t *n = NODE_DATA(node);
82 struct page *map = n->node_mem_map - n->node_start_pfn; 82 struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn;
83 83
84 for_each_nodebank (i,mi,node) { 84 for_each_nodebank (i,mi,node) {
85 struct membank *bank = &mi->bank[i]; 85 struct membank *bank = &mi->bank[i];
@@ -207,10 +207,8 @@ static inline void map_memory_bank(struct membank *bank)
207#endif 207#endif
208} 208}
209 209
210static unsigned long __init 210static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
211bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
212{ 211{
213 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
214 unsigned long start_pfn, end_pfn, boot_pfn; 212 unsigned long start_pfn, end_pfn, boot_pfn;
215 unsigned int boot_pages; 213 unsigned int boot_pages;
216 pg_data_t *pgdat; 214 pg_data_t *pgdat;
@@ -260,6 +258,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
260 for_each_nodebank(i, mi, node) { 258 for_each_nodebank(i, mi, node) {
261 struct membank *bank = &mi->bank[i]; 259 struct membank *bank = &mi->bank[i];
262 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); 260 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
261 memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
263 } 262 }
264 263
265 /* 264 /*
@@ -268,31 +267,39 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
268 reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, 267 reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
269 boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); 268 boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
270 269
271 /* 270 return end_pfn;
272 * Reserve any special node zero regions. 271}
273 */
274 if (node == 0)
275 reserve_node_zero(pgdat);
276 272
273static void __init bootmem_reserve_initrd(int node)
274{
277#ifdef CONFIG_BLK_DEV_INITRD 275#ifdef CONFIG_BLK_DEV_INITRD
278 /* 276 pg_data_t *pgdat = NODE_DATA(node);
279 * If the initrd is in this node, reserve its memory. 277 int res;
280 */ 278
281 if (node == initrd_node) { 279 res = reserve_bootmem_node(pgdat, phys_initrd_start,
282 int res = reserve_bootmem_node(pgdat, phys_initrd_start, 280 phys_initrd_size, BOOTMEM_EXCLUSIVE);
283 phys_initrd_size, BOOTMEM_EXCLUSIVE); 281
284 282 if (res == 0) {
285 if (res == 0) { 283 initrd_start = __phys_to_virt(phys_initrd_start);
286 initrd_start = __phys_to_virt(phys_initrd_start); 284 initrd_end = initrd_start + phys_initrd_size;
287 initrd_end = initrd_start + phys_initrd_size; 285 } else {
288 } else { 286 printk(KERN_ERR
289 printk(KERN_ERR 287 "INITRD: 0x%08lx+0x%08lx overlaps in-use "
290 "INITRD: 0x%08lx+0x%08lx overlaps in-use " 288 "memory region - disabling initrd\n",
291 "memory region - disabling initrd\n", 289 phys_initrd_start, phys_initrd_size);
292 phys_initrd_start, phys_initrd_size);
293 }
294 } 290 }
295#endif 291#endif
292}
293
294static void __init bootmem_free_node(int node, struct meminfo *mi)
295{
296 unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
297 unsigned long start_pfn, end_pfn;
298 pg_data_t *pgdat = NODE_DATA(node);
299 int i;
300
301 start_pfn = pgdat->bdata->node_min_pfn;
302 end_pfn = pgdat->bdata->node_low_pfn;
296 303
297 /* 304 /*
298 * initialise the zones within this node. 305 * initialise the zones within this node.
@@ -322,8 +329,6 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
322 arch_adjust_zones(node, zone_size, zhole_size); 329 arch_adjust_zones(node, zone_size, zhole_size);
323 330
324 free_area_init_node(node, zone_size, start_pfn, zhole_size); 331 free_area_init_node(node, zone_size, start_pfn, zhole_size);
325
326 return end_pfn;
327} 332}
328 333
329void __init bootmem_init(struct meminfo *mi) 334void __init bootmem_init(struct meminfo *mi)
@@ -342,9 +347,19 @@ void __init bootmem_init(struct meminfo *mi)
342 * Run through each node initialising the bootmem allocator. 347 * Run through each node initialising the bootmem allocator.
343 */ 348 */
344 for_each_node(node) { 349 for_each_node(node) {
345 unsigned long end_pfn; 350 unsigned long end_pfn = bootmem_init_node(node, mi);
346 351
347 end_pfn = bootmem_init_node(node, initrd_node, mi); 352 /*
353 * Reserve any special node zero regions.
354 */
355 if (node == 0)
356 reserve_node_zero(NODE_DATA(node));
357
358 /*
359 * If the initrd is in this node, reserve its memory.
360 */
361 if (node == initrd_node)
362 bootmem_reserve_initrd(node);
348 363
349 /* 364 /*
350 * Remember the highest memory PFN. 365 * Remember the highest memory PFN.
@@ -353,6 +368,19 @@ void __init bootmem_init(struct meminfo *mi)
353 memend_pfn = end_pfn; 368 memend_pfn = end_pfn;
354 } 369 }
355 370
371 /*
372 * sparse_init() needs the bootmem allocator up and running.
373 */
374 sparse_init();
375
376 /*
377 * Now free memory in each node - free_area_init_node needs
378 * the sparse mem_map arrays initialized by sparse_init()
379 * for memmap_init_zone(), otherwise all PFNs are invalid.
380 */
381 for_each_node(node)
382 bootmem_free_node(node, mi);
383
356 high_memory = __va(memend_pfn << PAGE_SHIFT); 384 high_memory = __va(memend_pfn << PAGE_SHIFT);
357 385
358 /* 386 /*