diff options
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r-- | mm/bootmem.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 1324cd74faec..2b0bcb019ec2 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -185,10 +185,23 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
185 | 185 | ||
186 | while (start < end) { | 186 | while (start < end) { |
187 | unsigned long *map, idx, vec; | 187 | unsigned long *map, idx, vec; |
188 | unsigned shift; | ||
188 | 189 | ||
189 | map = bdata->node_bootmem_map; | 190 | map = bdata->node_bootmem_map; |
190 | idx = start - bdata->node_min_pfn; | 191 | idx = start - bdata->node_min_pfn; |
192 | shift = idx & (BITS_PER_LONG - 1); | ||
193 | /* | ||
194 | * vec holds at most BITS_PER_LONG map bits, | ||
195 | * bit 0 corresponds to start. | ||
196 | */ | ||
191 | vec = ~map[idx / BITS_PER_LONG]; | 197 | vec = ~map[idx / BITS_PER_LONG]; |
198 | |||
199 | if (shift) { | ||
200 | vec >>= shift; | ||
201 | if (end - start >= BITS_PER_LONG) | ||
202 | vec |= ~map[idx / BITS_PER_LONG + 1] << | ||
203 | (BITS_PER_LONG - shift); | ||
204 | } | ||
192 | /* | 205 | /* |
193 | * If we have a properly aligned and fully unreserved | 206 | * If we have a properly aligned and fully unreserved |
194 | * BITS_PER_LONG block of pages in front of us, free | 207 | * BITS_PER_LONG block of pages in front of us, free |
@@ -201,19 +214,18 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
201 | count += BITS_PER_LONG; | 214 | count += BITS_PER_LONG; |
202 | start += BITS_PER_LONG; | 215 | start += BITS_PER_LONG; |
203 | } else { | 216 | } else { |
204 | unsigned long off = 0; | 217 | unsigned long cur = start; |
205 | 218 | ||
206 | vec >>= start & (BITS_PER_LONG - 1); | 219 | start = ALIGN(start + 1, BITS_PER_LONG); |
207 | while (vec) { | 220 | while (vec && cur != start) { |
208 | if (vec & 1) { | 221 | if (vec & 1) { |
209 | page = pfn_to_page(start + off); | 222 | page = pfn_to_page(cur); |
210 | __free_pages_bootmem(page, 0); | 223 | __free_pages_bootmem(page, 0); |
211 | count++; | 224 | count++; |
212 | } | 225 | } |
213 | vec >>= 1; | 226 | vec >>= 1; |
214 | off++; | 227 | ++cur; |
215 | } | 228 | } |
216 | start = ALIGN(start + 1, BITS_PER_LONG); | ||
217 | } | 229 | } |
218 | } | 230 | } |
219 | 231 | ||
@@ -821,6 +833,14 @@ void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, | |||
821 | return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT); | 833 | return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT); |
822 | } | 834 | } |
823 | 835 | ||
836 | void * __init __alloc_bootmem_low_nopanic(unsigned long size, | ||
837 | unsigned long align, | ||
838 | unsigned long goal) | ||
839 | { | ||
840 | return ___alloc_bootmem_nopanic(size, align, goal, | ||
841 | ARCH_LOW_ADDRESS_LIMIT); | ||
842 | } | ||
843 | |||
824 | /** | 844 | /** |
825 | * __alloc_bootmem_low_node - allocate low boot memory from a specific node | 845 | * __alloc_bootmem_low_node - allocate low boot memory from a specific node |
826 | * @pgdat: node to allocate from | 846 | * @pgdat: node to allocate from |