aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-28 07:56:42 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-28 07:56:42 -0700
commitc8339002de4fcb6b30c20f8676e92d30d04d5d87 (patch)
tree118c0c5d3600d935921a9859b802aa8f56649d07 /mm
parent2ac5f852bd0634c585a6cf55c78bc457f451dcdf (diff)
parent75e1802f052e595738683a00122ddf9577dcd456 (diff)
downloadhistory-c8339002de4fcb6b30c20f8676e92d30d04d5d87.tar.gz
Merge bk://linux-voyager.bkbits.net/dma-declare-coherent-memory-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'mm')
-rw-r--r--mm/vmalloc.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a4c7c0a17e9617..e9c5fb286899fc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -179,11 +179,26 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
return err;
}
+#define IOREMAP_MAX_ORDER (7 + PAGE_SHIFT) /* 128 pages */
+
struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end)
{
struct vm_struct **p, *tmp, *area;
- unsigned long addr = start;
+ unsigned long align = 1;
+ unsigned long addr;
+
+ if (flags & VM_IOREMAP) {
+ int bit = fls(size);
+
+ if (bit > IOREMAP_MAX_ORDER)
+ bit = IOREMAP_MAX_ORDER;
+ else if (bit < PAGE_SHIFT)
+ bit = PAGE_SHIFT;
+
+ align = 1ul << bit;
+ }
+ addr = ALIGN(start, align);
area = kmalloc(sizeof(*area), GFP_KERNEL);
if (unlikely(!area))
@@ -200,13 +215,17 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
write_lock(&vmlist_lock);
for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
- if ((unsigned long)tmp->addr < addr)
+ if ((unsigned long)tmp->addr < addr) {
+ if((unsigned long)tmp->addr + tmp->size >= addr)
+ addr = ALIGN(tmp->size +
+ (unsigned long)tmp->addr, align);
continue;
+ }
if ((size + addr) < addr)
goto out;
if (size + addr <= (unsigned long)tmp->addr)
goto found;
- addr = tmp->size + (unsigned long)tmp->addr;
+ addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
if (addr > end - size)
goto out;
}