summaryrefslogtreecommitdiffstats
path: root/mm/vmalloc.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
commit546db14ee74118296f425f3b91634fb767d67290 (patch)
tree22b613a3da8d4bf663eec5e155af01b87fdf9094 /mm/vmalloc.c
parent1e25e41c4f5474e14452094492dbc169b800e4c8 (diff)
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles and IP27 actually works.
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r--mm/vmalloc.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 9bd4142c3..1c436af20 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -20,7 +20,7 @@ static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned lo
if (pmd_none(*pmd))
return;
if (pmd_bad(*pmd)) {
- printk("free_area_pte: bad pmd (%08lx)\n", pmd_val(*pmd));
+ pmd_ERROR(*pmd);
pmd_clear(pmd);
return;
}
@@ -29,7 +29,7 @@ static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned lo
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
- while (address < end) {
+ do {
pte_t page = *pte;
pte_clear(pte);
address += PAGE_SIZE;
@@ -37,11 +37,13 @@ static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned lo
if (pte_none(page))
continue;
if (pte_present(page)) {
- free_page(pte_page(page));
+ unsigned long map_nr = pte_pagenr(page);
+ if (map_nr < max_mapnr)
+ __free_page(mem_map + map_nr);
continue;
}
printk("Whee.. Swapped out page in kernel page table\n");
- }
+ } while (address < end);
}
static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size)
@@ -52,7 +54,7 @@ static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned lo
if (pgd_none(*dir))
return;
if (pgd_bad(*dir)) {
- printk("free_area_pmd: bad pgd (%08lx)\n", pgd_val(*dir));
+ pgd_ERROR(*dir);
pgd_clear(dir);
return;
}
@@ -61,11 +63,11 @@ static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned lo
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
- while (address < end) {
+ do {
free_area_pte(pmd, address, end - address);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
- }
+ } while (address < end);
}
void vmfree_area_pages(unsigned long address, unsigned long size)
@@ -75,11 +77,11 @@ void vmfree_area_pages(unsigned long address, unsigned long size)
dir = pgd_offset_k(address);
flush_cache_all();
- while (address < end) {
+ do {
free_area_pmd(dir, address, end - address);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
- }
+ } while (address && (address < end));
flush_tlb_all();
}
@@ -91,17 +93,17 @@ static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned lo
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
- while (address < end) {
- unsigned long page;
+ do {
+ struct page * page;
if (!pte_none(*pte))
printk("alloc_area_pte: page already exists\n");
- page = __get_free_page(GFP_KERNEL|GFP_BIGMEM);
+ page = get_free_highpage(GFP_KERNEL|__GFP_HIGHMEM);
if (!page)
return -ENOMEM;
set_pte(pte, mk_pte(page, prot));
address += PAGE_SIZE;
pte++;
- }
+ } while (address < end);
return 0;
}
@@ -113,7 +115,7 @@ static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
- while (address < end) {
+ do {
pte_t * pte = pte_alloc_kernel(pmd, address);
if (!pte)
return -ENOMEM;
@@ -121,7 +123,7 @@ static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
return -ENOMEM;
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
- }
+ } while (address < end);
return 0;
}
@@ -132,7 +134,7 @@ int vmalloc_area_pages(unsigned long address, unsigned long size, pgprot_t prot)
dir = pgd_offset_k(address);
flush_cache_all();
- while (address < end) {
+ do {
pmd_t *pmd;
pgd_t olddir = *dir;
@@ -145,7 +147,7 @@ int vmalloc_area_pages(unsigned long address, unsigned long size, pgprot_t prot)
set_pgdir(address, *dir);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
- }
+ } while (address && (address < end));
flush_tlb_all();
return 0;
}
@@ -202,14 +204,19 @@ void * vmalloc_prot(unsigned long size, pgprot_t prot)
struct vm_struct *area;
size = PAGE_ALIGN(size);
- if (!size || size > (max_mapnr << PAGE_SHIFT))
+ if (!size || size > (max_mapnr << PAGE_SHIFT)) {
+ BUG();
return NULL;
+ }
area = get_vm_area(size);
- if (!area)
+ if (!area) {
+ BUG();
return NULL;
+ }
addr = area->addr;
if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, prot)) {
vfree(addr);
+ BUG();
return NULL;
}
return addr;