diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-07-21 23:34:31 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-07-21 23:34:31 +0200 |
commit | 088eb2a84b3b093af60bbe0b65151e8a9cd2d57d (patch) | |
tree | 8f145d8c71f6e249d6664b5482ac216b8c6e4016 /mm/sparse.c | |
parent | 6217a69a1e38807b3046b4fd6e4bf413e0e03b67 (diff) | |
parent | 84a1caf1453c3d44050bd22db958af4a7f99315c (diff) |
Merge tag 'v3.5-rc7' into late/soc
Linux 3.5-rc7
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) |