filemap: fix kernel-doc warnings
[safe/jmp/linux-2.6] / mm / bootmem.c
index 4af15d0..daf9271 100644 (file)
@@ -48,7 +48,7 @@ early_param("bootmem_debug", bootmem_debug_setup);
        if (unlikely(bootmem_debug))                    \
                printk(KERN_INFO                        \
                        "bootmem::%s " fmt,             \
-                       __FUNCTION__, ## args);         \
+                       __func__, ## args);             \
 })
 
 static unsigned long __init bootmap_bytes(unsigned long pages)
@@ -382,7 +382,6 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
        return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);
 }
 
-#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 /**
  * reserve_bootmem - mark a page range as usable
  * @addr: starting address of the range
@@ -403,15 +402,41 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size,
 
        return mark_bootmem(start, end, 1, flags);
 }
-#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
+
+static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx,
+                       unsigned long step)
+{
+       unsigned long base = bdata->node_min_pfn;
+
+       /*
+        * Align the index with respect to the node start so that the
+        * combination of both satisfies the requested alignment.
+        */
+
+       return ALIGN(base + idx, step) - base;
+}
+
+static unsigned long align_off(struct bootmem_data *bdata, unsigned long off,
+                       unsigned long align)
+{
+       unsigned long base = PFN_PHYS(bdata->node_min_pfn);
+
+       /* Same as align_idx for byte offsets */
+
+       return ALIGN(base + off, align) - base;
+}
 
 static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
-                               unsigned long size, unsigned long align,
-                               unsigned long goal, unsigned long limit)
+                                       unsigned long size, unsigned long align,
+                                       unsigned long goal, unsigned long limit)
 {
        unsigned long fallback = 0;
        unsigned long min, max, start, sidx, midx, step;
 
+       bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx\n",
+               bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT,
+               align, goal, limit);
+
        BUG_ON(!size);
        BUG_ON(align & (align - 1));
        BUG_ON(limit && goal + size > limit);
@@ -419,10 +444,6 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
        if (!bdata->node_bootmem_map)
                return NULL;
 
-       bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx\n",
-               bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT,
-               align, goal, limit);
-
        min = bdata->node_min_pfn;
        max = bdata->node_low_pfn;
 
@@ -441,7 +462,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
        else
                start = ALIGN(min, step);
 
-       sidx = start - bdata->node_min_pfn;;
+       sidx = start - bdata->node_min_pfn;
        midx = max - bdata->node_min_pfn;
 
        if (bdata->hint_idx > sidx) {
@@ -450,7 +471,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
                 * catch the fallback below.
                 */
                fallback = sidx + 1;
-               sidx = ALIGN(bdata->hint_idx, step);
+               sidx = align_idx(bdata, bdata->hint_idx, step);
        }
 
        while (1) {
@@ -459,7 +480,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
                unsigned long eidx, i, start_off, end_off;
 find_block:
                sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx);
-               sidx = ALIGN(sidx, step);
+               sidx = align_idx(bdata, sidx, step);
                eidx = sidx + PFN_UP(size);
 
                if (sidx >= midx || eidx > midx)
@@ -467,15 +488,15 @@ find_block:
 
                for (i = sidx; i < eidx; i++)
                        if (test_bit(i, bdata->node_bootmem_map)) {
-                               sidx = ALIGN(i, step);
+                               sidx = align_idx(bdata, i, step);
                                if (sidx == i)
                                        sidx += step;
                                goto find_block;
                        }
 
-               if (bdata->last_end_off &&
+               if (bdata->last_end_off & (PAGE_SIZE - 1) &&
                                PFN_DOWN(bdata->last_end_off) + 1 == sidx)
-                       start_off = ALIGN(bdata->last_end_off, align);
+                       start_off = align_off(bdata, bdata->last_end_off, align);
                else
                        start_off = PFN_PHYS(sidx);
 
@@ -499,7 +520,7 @@ find_block:
        }
 
        if (fallback) {
-               sidx = ALIGN(fallback - 1, step);
+               sidx = align_idx(bdata, fallback - 1, step);
                fallback = 0;
                goto find_block;
        }
@@ -507,17 +528,34 @@ find_block:
        return NULL;
 }
 
+static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata,
+                                       unsigned long size, unsigned long align,
+                                       unsigned long goal, unsigned long limit)
+{
+#ifdef CONFIG_HAVE_ARCH_BOOTMEM
+       bootmem_data_t *p_bdata;
+
+       p_bdata = bootmem_arch_preferred_node(bdata, size, align, goal, limit);
+       if (p_bdata)
+               return alloc_bootmem_core(p_bdata, size, align, goal, limit);
+#endif
+       return NULL;
+}
+
 static void * __init ___alloc_bootmem_nopanic(unsigned long size,
                                        unsigned long align,
                                        unsigned long goal,
                                        unsigned long limit)
 {
        bootmem_data_t *bdata;
+       void *region;
 
 restart:
-       list_for_each_entry(bdata, &bdata_list, list) {
-               void *region;
+       region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit);
+       if (region)
+               return region;
 
+       list_for_each_entry(bdata, &bdata_list, list) {
                if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
                        continue;
                if (limit && bdata->node_min_pfn >= PFN_DOWN(limit))
@@ -595,6 +633,10 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 {
        void *ptr;
 
+       ptr = alloc_arch_preferred_bootmem(bdata, size, align, goal, limit);
+       if (ptr)
+               return ptr;
+
        ptr = alloc_bootmem_core(bdata, size, align, goal, limit);
        if (ptr)
                return ptr;
@@ -651,6 +693,10 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
 {
        void *ptr;
 
+       ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0);
+       if (ptr)
+               return ptr;
+
        ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
        if (ptr)
                return ptr;