diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /mm/vmalloc.c | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r-- | mm/vmalloc.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6b87beaa2..e7711c23c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -135,12 +135,16 @@ int vmalloc_area_pages(unsigned long address, unsigned long size, pgprot_t prot) dir = pgd_offset_k(address); flush_cache_all(); while (address < end) { - pmd_t *pmd = pmd_alloc_kernel(dir, address); + pmd_t *pmd; + pgd_t olddir = *dir; + + pmd = pmd_alloc_kernel(dir, address); if (!pmd) return -ENOMEM; if (alloc_area_pmd(pmd, address, end - address, prot)) return -ENOMEM; - set_pgdir(address, *dir); + if (pgd_val(olddir) != pgd_val(*dir)) + set_pgdir(address, *dir); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } @@ -150,21 +154,22 @@ int vmalloc_area_pages(unsigned long address, unsigned long size, pgprot_t prot) struct vm_struct * get_vm_area(unsigned long size) { - void *addr; + unsigned long addr; struct vm_struct **p, *tmp, *area; area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); if (!area) return NULL; - addr = (void *) VMALLOC_START; - area->size = size + PAGE_SIZE; - area->next = NULL; + addr = VMALLOC_START; for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { - if (size + (unsigned long) addr < (unsigned long) tmp->addr) + if (size + addr < (unsigned long) tmp->addr) break; - addr = (void *) (tmp->size + (unsigned long) tmp->addr); + if (addr > VMALLOC_END-size) + return NULL; + addr = tmp->size + (unsigned long) tmp->addr; } - area->addr = addr; + area->addr = (void *)addr; + area->size = size + PAGE_SIZE; area->next = *p; *p = area; return area; @@ -217,16 +222,18 @@ void * vmalloc(unsigned long size) long vread(char *buf, char *addr, unsigned long count) { - struct vm_struct **p, *tmp; + struct vm_struct *tmp; char *vaddr, *buf_start = buf; - int n; + unsigned long n; /* Don't allow overflow */ if ((unsigned long) addr + count < count) count = -(unsigned long) addr; - for (p = &vmlist; (tmp = *p) ; p = &tmp->next) { + for (tmp = vmlist; tmp; tmp = tmp->next) { vaddr = (char *) tmp->addr; + if (addr >= vaddr + tmp->size - PAGE_SIZE) + continue; while (addr < vaddr) { if (count == 0) goto finished; @@ -235,17 +242,15 @@ long vread(char *buf, char *addr, unsigned long count) addr++; count--; } - n = tmp->size - PAGE_SIZE; - if (addr > vaddr) - n -= addr - vaddr; - while (--n >= 0) { + n = vaddr + tmp->size - PAGE_SIZE - addr; + do { if (count == 0) goto finished; put_user(*addr, buf); buf++; addr++; count--; - } + } while (--n > 0); } finished: return buf - buf_start; |