aboutsummaryrefslogtreecommitdiffstats
path: root/mm/bootmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r--mm/bootmem.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 8ec4e4c2a179..a58699b6579e 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -61,17 +61,9 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
61{ 61{
62 bootmem_data_t *bdata = pgdat->bdata; 62 bootmem_data_t *bdata = pgdat->bdata;
63 unsigned long mapsize = ((end - start)+7)/8; 63 unsigned long mapsize = ((end - start)+7)/8;
64 static struct pglist_data *pgdat_last; 64
65 65 pgdat->pgdat_next = pgdat_list;
66 pgdat->pgdat_next = NULL; 66 pgdat_list = pgdat;
67 /* Add new nodes last so that bootmem always starts
68 searching in the first nodes, not the last ones */
69 if (pgdat_last)
70 pgdat_last->pgdat_next = pgdat;
71 else {
72 pgdat_list = pgdat;
73 pgdat_last = pgdat;
74 }
75 67
76 mapsize = ALIGN(mapsize, sizeof(long)); 68 mapsize = ALIGN(mapsize, sizeof(long));
77 bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT); 69 bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
@@ -162,10 +154,10 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
162 */ 154 */
163static void * __init 155static void * __init
164__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, 156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
165 unsigned long align, unsigned long goal) 157 unsigned long align, unsigned long goal, unsigned long limit)
166{ 158{
167 unsigned long offset, remaining_size, areasize, preferred; 159 unsigned long offset, remaining_size, areasize, preferred;
168 unsigned long i, start = 0, incr, eidx; 160 unsigned long i, start = 0, incr, eidx, end_pfn = bdata->node_low_pfn;
169 void *ret; 161 void *ret;
170 162
171 if(!size) { 163 if(!size) {
@@ -174,7 +166,14 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
174 } 166 }
175 BUG_ON(align & (align-1)); 167 BUG_ON(align & (align-1));
176 168
177 eidx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT); 169 if (limit && bdata->node_boot_start >= limit)
170 return NULL;
171
172 limit >>=PAGE_SHIFT;
173 if (limit && end_pfn > limit)
174 end_pfn = limit;
175
176 eidx = end_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
178 offset = 0; 177 offset = 0;
179 if (align && 178 if (align &&
180 (bdata->node_boot_start & (align - 1UL)) != 0) 179 (bdata->node_boot_start & (align - 1UL)) != 0)
@@ -186,11 +185,12 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
186 * first, then we try to allocate lower pages. 185 * first, then we try to allocate lower pages.
187 */ 186 */
188 if (goal && (goal >= bdata->node_boot_start) && 187 if (goal && (goal >= bdata->node_boot_start) &&
189 ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) { 188 ((goal >> PAGE_SHIFT) < end_pfn)) {
190 preferred = goal - bdata->node_boot_start; 189 preferred = goal - bdata->node_boot_start;
191 190
192 if (bdata->last_success >= preferred) 191 if (bdata->last_success >= preferred)
193 preferred = bdata->last_success; 192 if (!limit || (limit && limit > bdata->last_success))
193 preferred = bdata->last_success;
194 } else 194 } else
195 preferred = 0; 195 preferred = 0;
196 196
@@ -390,14 +390,15 @@ unsigned long __init free_all_bootmem (void)
390 return(free_all_bootmem_core(NODE_DATA(0))); 390 return(free_all_bootmem_core(NODE_DATA(0)));
391} 391}
392 392
393void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal) 393void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal,
394 unsigned long limit)
394{ 395{
395 pg_data_t *pgdat = pgdat_list; 396 pg_data_t *pgdat = pgdat_list;
396 void *ptr; 397 void *ptr;
397 398
398 for_each_pgdat(pgdat) 399 for_each_pgdat(pgdat)
399 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, 400 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
400 align, goal))) 401 align, goal, limit)))
401 return(ptr); 402 return(ptr);
402 403
403 /* 404 /*
@@ -408,14 +409,16 @@ void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned
408 return NULL; 409 return NULL;
409} 410}
410 411
411void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) 412
413void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align,
414 unsigned long goal, unsigned long limit)
412{ 415{
413 void *ptr; 416 void *ptr;
414 417
415 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal); 418 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit);
416 if (ptr) 419 if (ptr)
417 return (ptr); 420 return (ptr);
418 421
419 return __alloc_bootmem(size, align, goal); 422 return __alloc_bootmem_limit(size, align, goal, limit);
420} 423}
421 424