aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorYasunori Goto <y-goto@jp.fujitsu.com>2005-10-19 18:52:18 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-20 02:11:33 -0400
commit281dd25cdc0d6903929b79183816d151ea626341 (patch)
treeed7898462492d853e422eb7f130f0b6e7efc0b69 /mm
parent51b190b304bbeb1090ba20b0623d39917fa62997 (diff)
[PATCH] swiotlb: make sure initial DMA allocations really are in DMA memory
This introduces a limit parameter to the core bootmem allocator; The new parameter indicates that physical memory allocated by the bootmem allocator should be within the requested limit. We also introduce alloc_bootmem_low_pages_limit, alloc_bootmem_node_limit, alloc_bootmem_low_pages_node_limit apis, but alloc_bootmem_low_pages_limit is the only api used for swiotlb. The existing alloc_bootmem_low_pages() api could instead have been changed and made to pass right limit to the core allocator. But that would make the patch more intrusive for 2.6.14, as other arches use alloc_bootmem_low_pages(). We may be done that post 2.6.14 as a cleanup. With this, swiotlb gets memory within 4G for both x86_64 and ia64 arches. Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com> Cc: Ravikiran G Thirumalai <kiran@scalex86.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/bootmem.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index c1330cc19783..a58699b6579e 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -154,10 +154,10 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
154 */ 154 */
155static void * __init 155static void * __init
156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, 156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
157 unsigned long align, unsigned long goal) 157 unsigned long align, unsigned long goal, unsigned long limit)
158{ 158{
159 unsigned long offset, remaining_size, areasize, preferred; 159 unsigned long offset, remaining_size, areasize, preferred;
160 unsigned long i, start = 0, incr, eidx; 160 unsigned long i, start = 0, incr, eidx, end_pfn = bdata->node_low_pfn;
161 void *ret; 161 void *ret;
162 162
163 if(!size) { 163 if(!size) {
@@ -166,7 +166,14 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
166 } 166 }
167 BUG_ON(align & (align-1)); 167 BUG_ON(align & (align-1));
168 168
169 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);
170 offset = 0; 177 offset = 0;
171 if (align && 178 if (align &&
172 (bdata->node_boot_start & (align - 1UL)) != 0) 179 (bdata->node_boot_start & (align - 1UL)) != 0)
@@ -178,11 +185,12 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
178 * first, then we try to allocate lower pages. 185 * first, then we try to allocate lower pages.
179 */ 186 */
180 if (goal && (goal >= bdata->node_boot_start) && 187 if (goal && (goal >= bdata->node_boot_start) &&
181 ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) { 188 ((goal >> PAGE_SHIFT) < end_pfn)) {
182 preferred = goal - bdata->node_boot_start; 189 preferred = goal - bdata->node_boot_start;
183 190
184 if (bdata->last_success >= preferred) 191 if (bdata->last_success >= preferred)
185 preferred = bdata->last_success; 192 if (!limit || (limit && limit > bdata->last_success))
193 preferred = bdata->last_success;
186 } else 194 } else
187 preferred = 0; 195 preferred = 0;
188 196
@@ -382,14 +390,15 @@ unsigned long __init free_all_bootmem (void)
382 return(free_all_bootmem_core(NODE_DATA(0))); 390 return(free_all_bootmem_core(NODE_DATA(0)));
383} 391}
384 392
385void * __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)
386{ 395{
387 pg_data_t *pgdat = pgdat_list; 396 pg_data_t *pgdat = pgdat_list;
388 void *ptr; 397 void *ptr;
389 398
390 for_each_pgdat(pgdat) 399 for_each_pgdat(pgdat)
391 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, 400 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
392 align, goal))) 401 align, goal, limit)))
393 return(ptr); 402 return(ptr);
394 403
395 /* 404 /*
@@ -400,14 +409,16 @@ void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned
400 return NULL; 409 return NULL;
401} 410}
402 411
403void * __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)
404{ 415{
405 void *ptr; 416 void *ptr;
406 417
407 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal); 418 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit);
408 if (ptr) 419 if (ptr)
409 return (ptr); 420 return (ptr);
410 421
411 return __alloc_bootmem(size, align, goal); 422 return __alloc_bootmem_limit(size, align, goal, limit);
412} 423}
413 424