[ARM] Clean up ioremap code

Since we're keeping the ioremap code, we might as well keep it as
close to the standard kernel as possible.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Russell King 2006-12-13 14:35:58 +00:00 committed by Russell King
parent ad1ae2fe7f
commit da2c12a279

View File

@ -38,89 +38,71 @@
*/
#define VM_ARM_SECTION_MAPPING 0x80000000
static inline void
remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, pgprot_t prot)
static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
unsigned long phys_addr, pgprot_t prot)
{
unsigned long end;
pte_t *pte;
pte = pte_alloc_kernel(pmd, addr);
if (!pte)
return -ENOMEM;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
BUG_ON(address >= end);
do {
if (!pte_none(*pte))
goto bad;
set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0);
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
pte++;
} while (address && (address < end));
return;
} while (pte++, addr += PAGE_SIZE, addr != end);
return 0;
bad:
printk("remap_area_pte: page already exists\n");
printk(KERN_CRIT "remap_area_pte: page already exists\n");
BUG();
}
static inline int
remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
unsigned long end, unsigned long phys_addr,
pgprot_t prot)
{
unsigned long end;
pgprot_t pgprot;
unsigned long next;
pmd_t *pmd;
int ret = 0;
address &= ~PGDIR_MASK;
end = address + size;
pmd = pmd_alloc(&init_mm, pgd, addr);
if (!pmd)
return -ENOMEM;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
phys_addr -= address;
BUG_ON(address >= end);
pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
do {
pte_t * pte = pte_alloc_kernel(pmd, address);
if (!pte)
return -ENOMEM;
remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
return 0;
next = pmd_addr_end(addr, end);
ret = remap_area_pte(pmd, addr, next, phys_addr, prot);
if (ret)
return ret;
phys_addr += next - addr;
} while (pmd++, addr = next, addr != end);
return ret;
}
static int
remap_area_pages(unsigned long start, unsigned long pfn,
unsigned long size, unsigned long flags)
static int remap_area_pages(unsigned long start, unsigned long pfn,
unsigned long size, unsigned long flags)
{
unsigned long address = start;
unsigned long end = start + size;
unsigned long addr = start;
unsigned long next, end = start + size;
unsigned long phys_addr = __pfn_to_phys(pfn);
pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
L_PTE_DIRTY | L_PTE_WRITE | flags);
pgd_t *pgd;
int err = 0;
pgd_t * dir;
phys_addr -= address;
dir = pgd_offset(&init_mm, address);
BUG_ON(address >= end);
BUG_ON(addr >= end);
pgd = pgd_offset_k(addr);
do {
pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
if (!pmd) {
err = -ENOMEM;
next = pgd_addr_end(addr, end);
err = remap_area_pmd(pgd, addr, next, phys_addr, prot);
if (err)
break;
}
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags)) {
err = -ENOMEM;
break;
}
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
phys_addr += next - addr;
} while (pgd++, addr = next, addr != end);
return err;
}