diff options
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r-- | mm/bootmem.c | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 94ea612deccf..9d03ff651359 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -225,6 +225,44 @@ unsigned long __init free_all_bootmem(void) | |||
225 | return free_all_bootmem_core(NODE_DATA(0)->bdata); | 225 | return free_all_bootmem_core(NODE_DATA(0)->bdata); |
226 | } | 226 | } |
227 | 227 | ||
228 | static void __init __free(bootmem_data_t *bdata, | ||
229 | unsigned long sidx, unsigned long eidx) | ||
230 | { | ||
231 | unsigned long idx; | ||
232 | |||
233 | bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data, | ||
234 | sidx + PFN_DOWN(bdata->node_boot_start), | ||
235 | eidx + PFN_DOWN(bdata->node_boot_start)); | ||
236 | |||
237 | for (idx = sidx; idx < eidx; idx++) | ||
238 | if (!test_and_clear_bit(idx, bdata->node_bootmem_map)) | ||
239 | BUG(); | ||
240 | } | ||
241 | |||
242 | static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx, | ||
243 | unsigned long eidx, int flags) | ||
244 | { | ||
245 | unsigned long idx; | ||
246 | int exclusive = flags & BOOTMEM_EXCLUSIVE; | ||
247 | |||
248 | bdebug("nid=%td start=%lx end=%lx flags=%x\n", | ||
249 | bdata - bootmem_node_data, | ||
250 | sidx + PFN_DOWN(bdata->node_boot_start), | ||
251 | eidx + PFN_DOWN(bdata->node_boot_start), | ||
252 | flags); | ||
253 | |||
254 | for (idx = sidx; idx < eidx; idx++) | ||
255 | if (test_and_set_bit(idx, bdata->node_bootmem_map)) { | ||
256 | if (exclusive) { | ||
257 | __free(bdata, sidx, idx); | ||
258 | return -EBUSY; | ||
259 | } | ||
260 | bdebug("silent double reserve of PFN %lx\n", | ||
261 | idx + PFN_DOWN(bdata->node_boot_start)); | ||
262 | } | ||
263 | return 0; | ||
264 | } | ||
265 | |||
228 | static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, | 266 | static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, |
229 | unsigned long size) | 267 | unsigned long size) |
230 | { | 268 | { |
@@ -258,14 +296,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, | |||
258 | if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) | 296 | if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) |
259 | eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); | 297 | eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); |
260 | 298 | ||
261 | bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data, | 299 | __free(bdata, sidx, eidx); |
262 | sidx + PFN_DOWN(bdata->node_boot_start), | ||
263 | eidx + PFN_DOWN(bdata->node_boot_start)); | ||
264 | |||
265 | for (i = sidx; i < eidx; i++) { | ||
266 | if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map))) | ||
267 | BUG(); | ||
268 | } | ||
269 | } | 300 | } |
270 | 301 | ||
271 | /** | 302 | /** |
@@ -367,16 +398,7 @@ static void __init reserve_bootmem_core(bootmem_data_t *bdata, | |||
367 | if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) | 398 | if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) |
368 | eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); | 399 | eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); |
369 | 400 | ||
370 | bdebug("nid=%td start=%lx end=%lx flags=%x\n", | 401 | return __reserve(bdata, sidx, eidx, flags); |
371 | bdata - bootmem_node_data, | ||
372 | sidx + PFN_DOWN(bdata->node_boot_start), | ||
373 | eidx + PFN_DOWN(bdata->node_boot_start), | ||
374 | flags); | ||
375 | |||
376 | for (i = sidx; i < eidx; i++) | ||
377 | if (test_and_set_bit(i, bdata->node_bootmem_map)) | ||
378 | bdebug("hm, page %lx reserved twice.\n", | ||
379 | PFN_DOWN(bdata->node_boot_start) + i); | ||
380 | } | 402 | } |
381 | 403 | ||
382 | /** | 404 | /** |
@@ -511,10 +533,9 @@ find_block: | |||
511 | /* | 533 | /* |
512 | * Reserve the area now: | 534 | * Reserve the area now: |
513 | */ | 535 | */ |
514 | for (i = PFN_DOWN(start_off) + merge; | 536 | if (__reserve(bdata, PFN_DOWN(start_off) + merge, |
515 | i < PFN_UP(end_off); i++) | 537 | PFN_UP(end_off), BOOTMEM_EXCLUSIVE)) |
516 | if (test_and_set_bit(i, bdata->node_bootmem_map)) | 538 | BUG(); |
517 | BUG(); | ||
518 | 539 | ||
519 | region = phys_to_virt(bdata->node_boot_start + start_off); | 540 | region = phys_to_virt(bdata->node_boot_start + start_off); |
520 | memset(region, 0, size); | 541 | memset(region, 0, size); |