diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-08 13:22:07 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-12-08 13:22:07 -0500 |
commit | 719361809fde9dbe9ccc4cf71f9fa9add5fa8bf9 (patch) | |
tree | e99a719d9605f12a7b00220e704736e54b4ee122 /mm | |
parent | 6a9ceb31c06f1e8d50be79259756fda73234868d (diff) |
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>
Diffstat (limited to 'mm')
-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) | |||
400 | return memblock_add_region(&memblock.memory, base, size); | 400 | return memblock_add_region(&memblock.memory, base, size); |
401 | } | 401 | } |
402 | 402 | ||
403 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | ||
404 | /** | 403 | /** |
405 | * memblock_isolate_range - isolate given range into disjoint memblocks | 404 | * memblock_isolate_range - isolate given range into disjoint memblocks |
406 | * @type: memblock type to isolate range for | 405 | * @type: memblock type to isolate range for |
@@ -449,7 +448,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, | |||
449 | rgn->base = base; | 448 | rgn->base = base; |
450 | rgn->size = rend - rgn->base; | 449 | rgn->size = rend - rgn->base; |
451 | memblock_insert_region(type, i, rbase, base - rbase, | 450 | memblock_insert_region(type, i, rbase, base - rbase, |
452 | rgn->nid); | 451 | memblock_get_region_node(rgn)); |
453 | } else if (rend > end) { | 452 | } else if (rend > end) { |
454 | /* | 453 | /* |
455 | * @rgn intersects from above. Split and redo the | 454 | * @rgn intersects from above. Split and redo the |
@@ -458,7 +457,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, | |||
458 | rgn->base = end; | 457 | rgn->base = end; |
459 | rgn->size = rend - rgn->base; | 458 | rgn->size = rend - rgn->base; |
460 | memblock_insert_region(type, i--, rbase, end - rbase, | 459 | memblock_insert_region(type, i--, rbase, end - rbase, |
461 | rgn->nid); | 460 | memblock_get_region_node(rgn)); |
462 | } else { | 461 | } else { |
463 | /* @rgn is fully contained, record it */ | 462 | /* @rgn is fully contained, record it */ |
464 | if (!*end_rgn) | 463 | if (!*end_rgn) |
@@ -469,56 +468,19 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, | |||
469 | 468 | ||
470 | return 0; | 469 | return 0; |
471 | } | 470 | } |
472 | #endif | ||
473 | 471 | ||
474 | static int __init_memblock __memblock_remove(struct memblock_type *type, | 472 | static int __init_memblock __memblock_remove(struct memblock_type *type, |
475 | phys_addr_t base, phys_addr_t size) | 473 | phys_addr_t base, phys_addr_t size) |
476 | { | 474 | { |
477 | phys_addr_t end = base + size; | 475 | int start_rgn, end_rgn; |
478 | int i; | 476 | int i, ret; |
479 | |||
480 | /* Walk through the array for collisions */ | ||
481 | for (i = 0; i < type->cnt; i++) { | ||
482 | struct memblock_region *rgn = &type->regions[i]; | ||
483 | phys_addr_t rend = rgn->base + rgn->size; | ||
484 | |||
485 | /* Nothing more to do, exit */ | ||
486 | if (rgn->base > end || rgn->size == 0) | ||
487 | break; | ||
488 | |||
489 | /* If we fully enclose the block, drop it */ | ||
490 | if (base <= rgn->base && end >= rend) { | ||
491 | memblock_remove_region(type, i--); | ||
492 | continue; | ||
493 | } | ||
494 | |||
495 | /* If we are fully enclosed within a block | ||
496 | * then we need to split it and we are done | ||
497 | */ | ||
498 | if (base > rgn->base && end < rend) { | ||
499 | rgn->size = base - rgn->base; | ||
500 | if (!memblock_add_region(type, end, rend - end)) | ||
501 | return 0; | ||
502 | /* Failure to split is bad, we at least | ||
503 | * restore the block before erroring | ||
504 | */ | ||
505 | rgn->size = rend - rgn->base; | ||
506 | WARN_ON(1); | ||
507 | return -1; | ||
508 | } | ||
509 | |||
510 | /* Check if we need to trim the bottom of a block */ | ||
511 | if (rgn->base < end && rend > end) { | ||
512 | rgn->size -= end - rgn->base; | ||
513 | rgn->base = end; | ||
514 | break; | ||
515 | } | ||
516 | 477 | ||
517 | /* And check if we need to trim the top of a block */ | 478 | ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn); |
518 | if (base < rend) | 479 | if (ret) |
519 | rgn->size -= rend - base; | 480 | return ret; |
520 | 481 | ||
521 | } | 482 | for (i = end_rgn - 1; i >= start_rgn; i--) |
483 | memblock_remove_region(type, i); | ||
522 | return 0; | 484 | return 0; |
523 | } | 485 | } |
524 | 486 | ||