summaryrefslogtreecommitdiffstats
path: root/mm/vmalloc.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /mm/vmalloc.c
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (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.c39
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;