diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-08 10:22:07 -0800 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-12-08 10:22:07 -0800 |
commit | 719361809fde9dbe9ccc4cf71f9fa9add5fa8bf9 (patch) | |
tree | e99a719d9605f12a7b00220e704736e54b4ee122 | |
parent | 6a9ceb31c06f1e8d50be79259756fda73234868d (diff) | |
download | lwn-719361809fde9dbe9ccc4cf71f9fa9add5fa8bf9.tar.gz lwn-719361809fde9dbe9ccc4cf71f9fa9add5fa8bf9.zip |
memblock: Reimplement __memblock_remove() using memblock_isolate_range()
__memblock_remove()'s open coded region manipulation can be trivially
replaced with memblock_islate_range(). This increases code sharing
and eases improving region tracking.
This pulls memblock_isolate_range() out of HAVE_MEMBLOCK_NODE_MAP.
Make it use memblock_get_region_node() instead of assuming rgn->nid is
available.
-v2: Fixed build failure on !HAVE_MEMBLOCK_NODE_MAP caused by direct
rgn->nid access.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Yinghai Lu <yinghai@kernel.org>
-rw-r--r-- | mm/memblock.c | 56 |
1 files changed, 9 insertions, 47 deletions
diff --git a/mm/memblock.c b/mm/memblock.c index a1e96a0fda00..fffe68b4bf14 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -400,7 +400,6 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) return memblock_add_region(&memblock.memory, base, size); } -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP /** * memblock_isolate_range - isolate given range into disjoint memblocks * @type: memblock type to isolate range for @@ -449,7 +448,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, rgn->base = base; rgn->size = rend - rgn->base; memblock_insert_region(type, i, rbase, base - rbase, - rgn->nid); + memblock_get_region_node(rgn)); } else if (rend > end) { /* * @rgn intersects from above. Split and redo the @@ -458,7 +457,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, rgn->base = end; rgn->size = rend - rgn->base; memblock_insert_region(type, i--, rbase, end - rbase, - rgn->nid); + memblock_get_region_node(rgn)); } else { /* @rgn is fully contained, record it */ if (!*end_rgn) @@ -469,56 +468,19 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, return 0; } -#endif static int __init_memblock __memblock_remove(struct memblock_type *type, phys_addr_t base, phys_addr_t size) { - phys_addr_t end = base + size; - int i; - - /* Walk through the array for collisions */ - for (i = 0; i < type->cnt; i++) { - struct memblock_region *rgn = &type->regions[i]; - phys_addr_t rend = rgn->base + rgn->size; - - /* Nothing more to do, exit */ - if (rgn->base > end || rgn->size == 0) - break; - - /* If we fully enclose the block, drop it */ - if (base <= rgn->base && end >= rend) { - memblock_remove_region(type, i--); - continue; - } - - /* If we are fully enclosed within a block - * then we need to split it and we are done - */ - if (base > rgn->base && end < rend) { - rgn->size = base - rgn->base; - if (!memblock_add_region(type, end, rend - end)) - return 0; - /* Failure to split is bad, we at least - * restore the block before erroring - */ - rgn->size = rend - rgn->base; - WARN_ON(1); - return -1; - } - - /* Check if we need to trim the bottom of a block */ - if (rgn->base < end && rend > end) { - rgn->size -= end - rgn->base; - rgn->base = end; - break; - } + int start_rgn, end_rgn; + int i, ret; - /* And check if we need to trim the top of a block */ - if (base < rend) - rgn->size -= rend - base; + ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn); + if (ret) + return ret; - } + for (i = end_rgn - 1; i >= start_rgn; i--) + memblock_remove_region(type, i); return 0; } |