mm: bootmem: allocate in order node+goal, goal, node, anywhere
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / bootmem.c
index 0131170..b5babdf 100644 (file)
@@ -203,7 +203,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                } else {
                        unsigned long off = 0;
 
-                       while (vec && off < BITS_PER_LONG) {
+                       vec >>= start & (BITS_PER_LONG - 1);
+                       while (vec) {
                                if (vec & 1) {
                                        page = pfn_to_page(start + off);
                                        __free_pages_bootmem(page, 0);
@@ -467,7 +468,7 @@ static unsigned long __init align_off(struct bootmem_data *bdata,
        return ALIGN(base + off, align) - base;
 }
 
-static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
+static void * __init alloc_bootmem_bdata(struct bootmem_data *bdata,
                                        unsigned long size, unsigned long align,
                                        unsigned long goal, unsigned long limit)
 {
@@ -588,14 +589,14 @@ static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata,
                p_bdata = bootmem_arch_preferred_node(bdata, size, align,
                                                        goal, limit);
                if (p_bdata)
-                       return alloc_bootmem_core(p_bdata, size, align,
+                       return alloc_bootmem_bdata(p_bdata, size, align,
                                                        goal, limit);
        }
 #endif
        return NULL;
 }
 
-static void * __init ___alloc_bootmem_nopanic(unsigned long size,
+static void * __init alloc_bootmem_core(unsigned long size,
                                        unsigned long align,
                                        unsigned long goal,
                                        unsigned long limit)
@@ -603,7 +604,6 @@ static void * __init ___alloc_bootmem_nopanic(unsigned long size,
        bootmem_data_t *bdata;
        void *region;
 
-restart:
        region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit);
        if (region)
                return region;
@@ -614,11 +614,25 @@ restart:
                if (limit && bdata->node_min_pfn >= PFN_DOWN(limit))
                        break;
 
-               region = alloc_bootmem_core(bdata, size, align, goal, limit);
+               region = alloc_bootmem_bdata(bdata, size, align, goal, limit);
                if (region)
                        return region;
        }
 
+       return NULL;
+}
+
+static void * __init ___alloc_bootmem_nopanic(unsigned long size,
+                                             unsigned long align,
+                                             unsigned long goal,
+                                             unsigned long limit)
+{
+       void *ptr;
+
+restart:
+       ptr = alloc_bootmem_core(size, align, goal, limit);
+       if (ptr)
+               return ptr;
        if (goal) {
                goal = 0;
                goto restart;
@@ -690,15 +704,27 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 {
        void *ptr;
 
+again:
        ptr = alloc_arch_preferred_bootmem(bdata, size, align, goal, limit);
        if (ptr)
                return ptr;
 
-       ptr = alloc_bootmem_core(bdata, size, align, goal, limit);
+       ptr = alloc_bootmem_bdata(bdata, size, align, goal, limit);
        if (ptr)
                return ptr;
 
-       return ___alloc_bootmem(size, align, goal, limit);
+       ptr = alloc_bootmem_core(size, align, goal, limit);
+       if (ptr)
+               return ptr;
+
+       if (goal) {
+               goal = 0;
+               goto again;
+       }
+
+       printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
+       panic("Out of memory");
+       return NULL;
 }
 
 /**
@@ -743,7 +769,7 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
                unsigned long new_goal;
 
                new_goal = MAX_DMA32_PFN << PAGE_SHIFT;
-               ptr = alloc_bootmem_core(pgdat->bdata, size, align,
+               ptr = alloc_bootmem_bdata(pgdat->bdata, size, align,
                                                 new_goal, 0);
                if (ptr)
                        return ptr;
@@ -772,7 +798,7 @@ void * __init alloc_bootmem_section(unsigned long size,
        goal = pfn << PAGE_SHIFT;
        bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
-       return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0);
+       return alloc_bootmem_bdata(bdata, size, SMP_CACHE_BYTES, goal, 0);
 }
 #endif
 
@@ -788,7 +814,7 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
        if (ptr)
                return ptr;
 
-       ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+       ptr = alloc_bootmem_bdata(pgdat->bdata, size, align, goal, 0);
        if (ptr)
                return ptr;