|
@@ -37,16 +37,6 @@ static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
|
|
|
|
|
|
static int bootmem_debug;
|
|
|
|
|
|
-/*
|
|
|
- * If an arch needs to apply workarounds to bootmem allocation, it can
|
|
|
- * set CONFIG_HAVE_ARCH_BOOTMEM and define a wrapper around
|
|
|
- * __alloc_bootmem_core().
|
|
|
- */
|
|
|
-#ifndef CONFIG_HAVE_ARCH_BOOTMEM
|
|
|
-#define alloc_bootmem_core(bdata, size, align, goal, limit) \
|
|
|
- __alloc_bootmem_core((bdata), (size), (align), (goal), (limit))
|
|
|
-#endif
|
|
|
-
|
|
|
static int __init bootmem_debug_setup(char *buf)
|
|
|
{
|
|
|
bootmem_debug = 1;
|
|
@@ -436,9 +426,9 @@ static unsigned long align_off(struct bootmem_data *bdata, unsigned long off,
|
|
|
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)
|
|
|
+static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
|
|
|
+ unsigned long size, unsigned long align,
|
|
|
+ unsigned long goal, unsigned long limit)
|
|
|
{
|
|
|
unsigned long fallback = 0;
|
|
|
unsigned long min, max, start, sidx, midx, step;
|
|
@@ -538,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))
|
|
@@ -626,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;
|
|
@@ -682,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;
|