aboutsummaryrefslogtreecommitdiffstats
path: root/mm/bootmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r--mm/bootmem.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index e5415a5414a5..89646f77b427 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -408,6 +408,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
408 unsigned long size, unsigned long align, 408 unsigned long size, unsigned long align,
409 unsigned long goal, unsigned long limit) 409 unsigned long goal, unsigned long limit)
410{ 410{
411 unsigned long fallback = 0;
411 unsigned long min, max, start, sidx, midx, step; 412 unsigned long min, max, start, sidx, midx, step;
412 413
413 BUG_ON(!size); 414 BUG_ON(!size);
@@ -443,8 +444,11 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
443 midx = max - PFN_DOWN(bdata->node_boot_start); 444 midx = max - PFN_DOWN(bdata->node_boot_start);
444 445
445 if (bdata->hint_idx > sidx) { 446 if (bdata->hint_idx > sidx) {
446 /* Make sure we retry on failure */ 447 /*
447 goal = 1; 448 * Handle the valid case of sidx being zero and still
449 * catch the fallback below.
450 */
451 fallback = sidx + 1;
448 sidx = ALIGN(bdata->hint_idx, step); 452 sidx = ALIGN(bdata->hint_idx, step);
449 } 453 }
450 454
@@ -492,10 +496,39 @@ find_block:
492 return region; 496 return region;
493 } 497 }
494 498
499 if (fallback) {
500 sidx = ALIGN(fallback - 1, step);
501 fallback = 0;
502 goto find_block;
503 }
504
505 return NULL;
506}
507
508static void * __init ___alloc_bootmem_nopanic(unsigned long size,
509 unsigned long align,
510 unsigned long goal,
511 unsigned long limit)
512{
513 bootmem_data_t *bdata;
514
515restart:
516 list_for_each_entry(bdata, &bdata_list, list) {
517 void *region;
518
519 if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
520 continue;
521 if (limit && bdata->node_boot_start >= limit)
522 break;
523
524 region = alloc_bootmem_core(bdata, size, align, goal, limit);
525 if (region)
526 return region;
527 }
528
495 if (goal) { 529 if (goal) {
496 goal = 0; 530 goal = 0;
497 sidx = 0; 531 goto restart;
498 goto find_block;
499 } 532 }
500 533
501 return NULL; 534 return NULL;
@@ -515,16 +548,23 @@ find_block:
515 * Returns NULL on failure. 548 * Returns NULL on failure.
516 */ 549 */
517void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, 550void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
518 unsigned long goal) 551 unsigned long goal)
519{ 552{
520 bootmem_data_t *bdata; 553 return ___alloc_bootmem_nopanic(size, align, goal, 0);
521 void *ptr; 554}
522 555
523 list_for_each_entry(bdata, &bdata_list, list) { 556static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
524 ptr = alloc_bootmem_core(bdata, size, align, goal, 0); 557 unsigned long goal, unsigned long limit)
525 if (ptr) 558{
526 return ptr; 559 void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);
527 } 560
561 if (mem)
562 return mem;
563 /*
564 * Whoops, we cannot satisfy the allocation request.
565 */
566 printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
567 panic("Out of memory");
528 return NULL; 568 return NULL;
529} 569}
530 570
@@ -544,16 +584,7 @@ void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
544void * __init __alloc_bootmem(unsigned long size, unsigned long align, 584void * __init __alloc_bootmem(unsigned long size, unsigned long align,
545 unsigned long goal) 585 unsigned long goal)
546{ 586{
547 void *mem = __alloc_bootmem_nopanic(size,align,goal); 587 return ___alloc_bootmem(size, align, goal, 0);
548
549 if (mem)
550 return mem;
551 /*
552 * Whoops, we cannot satisfy the allocation request.
553 */
554 printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
555 panic("Out of memory");
556 return NULL;
557} 588}
558 589
559/** 590/**
@@ -653,22 +684,7 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
653void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, 684void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
654 unsigned long goal) 685 unsigned long goal)
655{ 686{
656 bootmem_data_t *bdata; 687 return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
657 void *ptr;
658
659 list_for_each_entry(bdata, &bdata_list, list) {
660 ptr = alloc_bootmem_core(bdata, size, align, goal,
661 ARCH_LOW_ADDRESS_LIMIT);
662 if (ptr)
663 return ptr;
664 }
665
666 /*
667 * Whoops, we cannot satisfy the allocation request.
668 */
669 printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size);
670 panic("Out of low memory");
671 return NULL;
672} 688}
673 689
674/** 690/**