diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-07-12 01:00:34 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-08-04 22:56:22 -0400 |
| commit | fef501d49d31f997a3381b6c1efd5bca382b6b6f (patch) | |
| tree | d228dd686367dd3a49fc4152cef94d83b99dad29 | |
| parent | d2cd563ba82c424083b78e0ce97d68bfb04d1242 (diff) | |
memblock: Add "start" argument to memblock_find_base()
To constraint the search of a region between two boundaries,
which will be used by the new NUMA aware allocator among others.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
| -rw-r--r-- | mm/memblock.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/mm/memblock.c b/mm/memblock.c index 8715f09434df..468ff43a72b4 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
| @@ -117,19 +117,18 @@ static phys_addr_t __init memblock_find_region(phys_addr_t start, phys_addr_t en | |||
| 117 | return MEMBLOCK_ERROR; | 117 | return MEMBLOCK_ERROR; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr) | 120 | static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align, |
| 121 | phys_addr_t start, phys_addr_t end) | ||
| 121 | { | 122 | { |
| 122 | long i; | 123 | long i; |
| 123 | phys_addr_t base = 0; | ||
| 124 | phys_addr_t res_base; | ||
| 125 | 124 | ||
| 126 | BUG_ON(0 == size); | 125 | BUG_ON(0 == size); |
| 127 | 126 | ||
| 128 | size = memblock_align_up(size, align); | 127 | size = memblock_align_up(size, align); |
| 129 | 128 | ||
| 130 | /* Pump up max_addr */ | 129 | /* Pump up max_addr */ |
| 131 | if (max_addr == MEMBLOCK_ALLOC_ACCESSIBLE) | 130 | if (end == MEMBLOCK_ALLOC_ACCESSIBLE) |
| 132 | max_addr = memblock.current_limit; | 131 | end = memblock.current_limit; |
| 133 | 132 | ||
| 134 | /* We do a top-down search, this tends to limit memory | 133 | /* We do a top-down search, this tends to limit memory |
| 135 | * fragmentation by keeping early boot allocs near the | 134 | * fragmentation by keeping early boot allocs near the |
| @@ -138,13 +137,19 @@ static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align | |||
| 138 | for (i = memblock.memory.cnt - 1; i >= 0; i--) { | 137 | for (i = memblock.memory.cnt - 1; i >= 0; i--) { |
| 139 | phys_addr_t memblockbase = memblock.memory.regions[i].base; | 138 | phys_addr_t memblockbase = memblock.memory.regions[i].base; |
| 140 | phys_addr_t memblocksize = memblock.memory.regions[i].size; | 139 | phys_addr_t memblocksize = memblock.memory.regions[i].size; |
| 140 | phys_addr_t bottom, top, found; | ||
| 141 | 141 | ||
| 142 | if (memblocksize < size) | 142 | if (memblocksize < size) |
| 143 | continue; | 143 | continue; |
| 144 | base = min(memblockbase + memblocksize, max_addr); | 144 | if ((memblockbase + memblocksize) <= start) |
| 145 | res_base = memblock_find_region(memblockbase, base, size, align); | 145 | break; |
| 146 | if (res_base != MEMBLOCK_ERROR) | 146 | bottom = max(memblockbase, start); |
| 147 | return res_base; | 147 | top = min(memblockbase + memblocksize, end); |
| 148 | if (bottom >= top) | ||
| 149 | continue; | ||
| 150 | found = memblock_find_region(bottom, top, size, align); | ||
| 151 | if (found != MEMBLOCK_ERROR) | ||
| 152 | return found; | ||
| 148 | } | 153 | } |
| 149 | return MEMBLOCK_ERROR; | 154 | return MEMBLOCK_ERROR; |
| 150 | } | 155 | } |
| @@ -204,7 +209,7 @@ static int memblock_double_array(struct memblock_type *type) | |||
| 204 | new_array = kmalloc(new_size, GFP_KERNEL); | 209 | new_array = kmalloc(new_size, GFP_KERNEL); |
| 205 | addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array); | 210 | addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array); |
| 206 | } else | 211 | } else |
| 207 | addr = memblock_find_base(new_size, sizeof(phys_addr_t), MEMBLOCK_ALLOC_ACCESSIBLE); | 212 | addr = memblock_find_base(new_size, sizeof(phys_addr_t), 0, MEMBLOCK_ALLOC_ACCESSIBLE); |
| 208 | if (addr == MEMBLOCK_ERROR) { | 213 | if (addr == MEMBLOCK_ERROR) { |
| 209 | pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", | 214 | pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", |
| 210 | memblock_type_name(type), type->max, type->max * 2); | 215 | memblock_type_name(type), type->max, type->max * 2); |
| @@ -416,7 +421,7 @@ phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, ph | |||
| 416 | */ | 421 | */ |
| 417 | size = memblock_align_up(size, align); | 422 | size = memblock_align_up(size, align); |
| 418 | 423 | ||
| 419 | found = memblock_find_base(size, align, max_addr); | 424 | found = memblock_find_base(size, align, 0, max_addr); |
| 420 | if (found != MEMBLOCK_ERROR && | 425 | if (found != MEMBLOCK_ERROR && |
| 421 | memblock_add_region(&memblock.reserved, found, size) >= 0) | 426 | memblock_add_region(&memblock.reserved, found, size) >= 0) |
| 422 | return found; | 427 | return found; |
