Commit b7a69ac3 authored by Russell King's avatar Russell King Committed by Russell King

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent d2a38ef9
...@@ -79,7 +79,7 @@ void show_mem(void) ...@@ -79,7 +79,7 @@ void show_mem(void)
show_free_areas(); show_free_areas();
for_each_online_node(node) { for_each_online_node(node) {
pg_data_t *n = NODE_DATA(node); pg_data_t *n = NODE_DATA(node);
struct page *map = n->node_mem_map - n->node_start_pfn; struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn;
for_each_nodebank (i,mi,node) { for_each_nodebank (i,mi,node) {
struct membank *bank = &mi->bank[i]; struct membank *bank = &mi->bank[i];
...@@ -207,10 +207,8 @@ static inline void map_memory_bank(struct membank *bank) ...@@ -207,10 +207,8 @@ static inline void map_memory_bank(struct membank *bank)
#endif #endif
} }
static unsigned long __init static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
{ {
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
unsigned long start_pfn, end_pfn, boot_pfn; unsigned long start_pfn, end_pfn, boot_pfn;
unsigned int boot_pages; unsigned int boot_pages;
pg_data_t *pgdat; pg_data_t *pgdat;
...@@ -260,6 +258,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) ...@@ -260,6 +258,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
for_each_nodebank(i, mi, node) { for_each_nodebank(i, mi, node) {
struct membank *bank = &mi->bank[i]; struct membank *bank = &mi->bank[i];
free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
} }
/* /*
...@@ -268,31 +267,39 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) ...@@ -268,31 +267,39 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
/* return end_pfn;
* Reserve any special node zero regions. }
*/
if (node == 0)
reserve_node_zero(pgdat);
static void __init bootmem_reserve_initrd(int node)
{
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
/* pg_data_t *pgdat = NODE_DATA(node);
* If the initrd is in this node, reserve its memory. int res;
*/
if (node == initrd_node) { res = reserve_bootmem_node(pgdat, phys_initrd_start,
int res = reserve_bootmem_node(pgdat, phys_initrd_start, phys_initrd_size, BOOTMEM_EXCLUSIVE);
phys_initrd_size, BOOTMEM_EXCLUSIVE);
if (res == 0) {
if (res == 0) { initrd_start = __phys_to_virt(phys_initrd_start);
initrd_start = __phys_to_virt(phys_initrd_start); initrd_end = initrd_start + phys_initrd_size;
initrd_end = initrd_start + phys_initrd_size; } else {
} else { printk(KERN_ERR
printk(KERN_ERR "INITRD: 0x%08lx+0x%08lx overlaps in-use "
"INITRD: 0x%08lx+0x%08lx overlaps in-use " "memory region - disabling initrd\n",
"memory region - disabling initrd\n", phys_initrd_start, phys_initrd_size);
phys_initrd_start, phys_initrd_size);
}
} }
#endif #endif
}
static void __init bootmem_free_node(int node, struct meminfo *mi)
{
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
unsigned long start_pfn, end_pfn;
pg_data_t *pgdat = NODE_DATA(node);
int i;
start_pfn = pgdat->bdata->node_min_pfn;
end_pfn = pgdat->bdata->node_low_pfn;
/* /*
* initialise the zones within this node. * initialise the zones within this node.
...@@ -322,8 +329,6 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) ...@@ -322,8 +329,6 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
arch_adjust_zones(node, zone_size, zhole_size); arch_adjust_zones(node, zone_size, zhole_size);
free_area_init_node(node, zone_size, start_pfn, zhole_size); free_area_init_node(node, zone_size, start_pfn, zhole_size);
return end_pfn;
} }
void __init bootmem_init(struct meminfo *mi) void __init bootmem_init(struct meminfo *mi)
...@@ -342,9 +347,19 @@ void __init bootmem_init(struct meminfo *mi) ...@@ -342,9 +347,19 @@ void __init bootmem_init(struct meminfo *mi)
* Run through each node initialising the bootmem allocator. * Run through each node initialising the bootmem allocator.
*/ */
for_each_node(node) { for_each_node(node) {
unsigned long end_pfn; unsigned long end_pfn = bootmem_init_node(node, mi);
end_pfn = bootmem_init_node(node, initrd_node, mi); /*
* Reserve any special node zero regions.
*/
if (node == 0)
reserve_node_zero(NODE_DATA(node));
/*
* If the initrd is in this node, reserve its memory.
*/
if (node == initrd_node)
bootmem_reserve_initrd(node);
/* /*
* Remember the highest memory PFN. * Remember the highest memory PFN.
...@@ -353,6 +368,19 @@ void __init bootmem_init(struct meminfo *mi) ...@@ -353,6 +368,19 @@ void __init bootmem_init(struct meminfo *mi)
memend_pfn = end_pfn; memend_pfn = end_pfn;
} }
/*
* sparse_init() needs the bootmem allocator up and running.
*/
sparse_init();
/*
* Now free memory in each node - free_area_init_node needs
* the sparse mem_map arrays initialized by sparse_init()
* for memmap_init_zone(), otherwise all PFNs are invalid.
*/
for_each_node(node)
bootmem_free_node(node, mi);
high_memory = __va(memend_pfn << PAGE_SHIFT); high_memory = __va(memend_pfn << PAGE_SHIFT);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment