summaryrefslogtreecommitdiffstats
path: root/mm/nobootmem.c
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2012-04-25 16:10:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-04-25 21:18:01 -0700
commit4e1c2b284461fd8aa8d7b295a1e911fc4390755b (patch)
treef51ab604d23af8ac0f6087516f877af5604c3477 /mm/nobootmem.c
parentaf3a3ab2966112c0d0a44df7eeb1e95fe32d4495 (diff)
downloadlinux-4e1c2b284461fd8aa8d7b295a1e911fc4390755b.tar.gz
linux-4e1c2b284461fd8aa8d7b295a1e911fc4390755b.tar.bz2
linux-4e1c2b284461fd8aa8d7b295a1e911fc4390755b.zip
mm: nobootmem: Correct alloc_bootmem semantics.
The comments above __alloc_bootmem_node() claim that the code will first try the allocation using 'goal' and if that fails it will try again but with the 'goal' requirement dropped. Unfortunately, this is not what the code does, so fix it to do so. This is important for nobootmem conversions to architectures such as sparc where MAX_DMA_ADDRESS is infinity. On such architectures all of the allocations done by generic spots, such as the sparse-vmemmap implementation, will pass in: __pa(MAX_DMA_ADDRESS) as the goal, and with the limit given as "-1" this will always fail unless we add the appropriate fallback logic here. Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/nobootmem.c')
-rw-r--r--mm/nobootmem.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index 24f0fc1a56d6..e53bb8a256b1 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -298,13 +298,19 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
if (WARN_ON_ONCE(slab_is_available()))
return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+again:
ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
goal, -1ULL);
if (ptr)
return ptr;
- return __alloc_memory_core_early(MAX_NUMNODES, size, align,
- goal, -1ULL);
+ ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
+ goal, -1ULL);
+ if (!ptr && goal) {
+ goal = 0;
+ goto again;
+ }
+ return ptr;
}
void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,