diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
commit | 546db14ee74118296f425f3b91634fb767d67290 (patch) | |
tree | 22b613a3da8d4bf663eec5e155af01b87fdf9094 /mm/vmalloc.c | |
parent | 1e25e41c4f5474e14452094492dbc169b800e4c8 (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.c | 45 |
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; |