diff options
Diffstat (limited to 'mm/sparse.c')
| -rw-r--r-- | mm/sparse.c | 20 | 
1 files changed, 14 insertions, 6 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index 6a4bf9160e8..c7bb952400c 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -275,8 +275,9 @@ static unsigned long * __init  sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,  					 unsigned long size)  { -	pg_data_t *host_pgdat; -	unsigned long goal; +	unsigned long goal, limit; +	unsigned long *p; +	int nid;  	/*  	 * A page may contain usemaps for other sections preventing the  	 * page being freed and making a section unremovable while @@ -287,10 +288,17 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,  	 * from the same section as the pgdat where possible to avoid  	 * this problem.  	 */ -	goal = __pa(pgdat) & PAGE_SECTION_MASK; -	host_pgdat = NODE_DATA(early_pfn_to_nid(goal >> PAGE_SHIFT)); -	return __alloc_bootmem_node_nopanic(host_pgdat, size, -					    SMP_CACHE_BYTES, goal); +	goal = __pa(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT); +	limit = goal + (1UL << PA_SECTION_SHIFT); +	nid = early_pfn_to_nid(goal >> PAGE_SHIFT); +again: +	p = ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size, +					  SMP_CACHE_BYTES, goal, limit); +	if (!p && limit) { +		limit = 0; +		goto again; +	} +	return p;  }  static void __init check_usemap_section_nr(int nid, unsigned long *usemap)  |