diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-07-06 15:39:14 -0700 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-05 12:56:21 +1000 |
commit | d2cd563ba82c424083b78e0ce97d68bfb04d1242 (patch) | |
tree | ff4ab6de8b6906a6c955aa51c4ee53868dfafc0a /mm/memblock.c | |
parent | 142b45a72e221537c1bb1995497fef7cdc439e26 (diff) | |
download | kernel-common-d2cd563ba82c424083b78e0ce97d68bfb04d1242.tar.gz kernel-common-d2cd563ba82c424083b78e0ce97d68bfb04d1242.tar.bz2 kernel-common-d2cd563ba82c424083b78e0ce97d68bfb04d1242.zip |
memblock: Add arch function to control coalescing of memblock memory regions
Some archs such as ARM want to avoid coalescing accross things such
as the lowmem/highmem boundary or similar. This provides the option
to control it via an arch callback for which a weak default is provided
which always allows coalescing.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'mm/memblock.c')
-rw-r--r-- | mm/memblock.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/mm/memblock.c b/mm/memblock.c index 0787790b1ce0..8715f09434df 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -241,6 +241,12 @@ static int memblock_double_array(struct memblock_type *type) return 0; } +extern int __weak memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1, + phys_addr_t addr2, phys_addr_t size2) +{ + return 1; +} + static long memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size) { unsigned long coalesced = 0; @@ -262,6 +268,10 @@ static long memblock_add_region(struct memblock_type *type, phys_addr_t base, ph return 0; adjacent = memblock_addrs_adjacent(base, size, rgnbase, rgnsize); + /* Check if arch allows coalescing */ + if (adjacent != 0 && type == &memblock.memory && + !memblock_memory_can_coalesce(base, size, rgnbase, rgnsize)) + break; if (adjacent > 0) { type->regions[i].base -= size; type->regions[i].size += size; @@ -274,7 +284,14 @@ static long memblock_add_region(struct memblock_type *type, phys_addr_t base, ph } } - if ((i < type->cnt - 1) && memblock_regions_adjacent(type, i, i+1)) { + /* If we plugged a hole, we may want to also coalesce with the + * next region + */ + if ((i < type->cnt - 1) && memblock_regions_adjacent(type, i, i+1) && + ((type != &memblock.memory || memblock_memory_can_coalesce(type->regions[i].base, + type->regions[i].size, + type->regions[i+1].base, + type->regions[i+1].size)))) { memblock_coalesce_regions(type, i, i+1); coalesced++; } |