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; |