Commit da2c12a2 authored by Russell King's avatar Russell King Committed by Russell King

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent ad1ae2fe
...@@ -38,89 +38,71 @@ ...@@ -38,89 +38,71 @@
*/ */
#define VM_ARM_SECTION_MAPPING 0x80000000 #define VM_ARM_SECTION_MAPPING 0x80000000
static inline void static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, pgprot_t prot)
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 { do {
if (!pte_none(*pte)) if (!pte_none(*pte))
goto bad; goto bad;
set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0); set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0);
address += PAGE_SIZE;
phys_addr += PAGE_SIZE; phys_addr += PAGE_SIZE;
pte++; } while (pte++, addr += PAGE_SIZE, addr != end);
} while (address && (address < end)); return 0;
return;
bad: bad:
printk("remap_area_pte: page already exists\n"); printk(KERN_CRIT "remap_area_pte: page already exists\n");
BUG(); BUG();
} }
static inline int static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, unsigned long end, unsigned long phys_addr,
unsigned long phys_addr, unsigned long flags) pgprot_t prot)
{ {
unsigned long end; unsigned long next;
pgprot_t pgprot; pmd_t *pmd;
int ret = 0;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE) pmd = pmd_alloc(&init_mm, pgd, addr);
end = PGDIR_SIZE; if (!pmd)
return -ENOMEM;
phys_addr -= address;
BUG_ON(address >= end);
pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
do { do {
pte_t * pte = pte_alloc_kernel(pmd, address); next = pmd_addr_end(addr, end);
if (!pte) ret = remap_area_pte(pmd, addr, next, phys_addr, prot);
return -ENOMEM; if (ret)
remap_area_pte(pte, address, end - address, address + phys_addr, pgprot); return ret;
address = (address + PMD_SIZE) & PMD_MASK; phys_addr += next - addr;
pmd++; } while (pmd++, addr = next, addr != end);
} while (address && (address < end)); return ret;
return 0;
} }
static int static int remap_area_pages(unsigned long start, unsigned long pfn,
remap_area_pages(unsigned long start, unsigned long pfn, unsigned long size, unsigned long flags)
unsigned long size, unsigned long flags)
{ {
unsigned long address = start; unsigned long addr = start;
unsigned long end = start + size; unsigned long next, end = start + size;
unsigned long phys_addr = __pfn_to_phys(pfn); 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; int err = 0;
pgd_t * dir;
phys_addr -= address; BUG_ON(addr >= end);
dir = pgd_offset(&init_mm, address); pgd = pgd_offset_k(addr);
BUG_ON(address >= end);
do { do {
pmd_t *pmd = pmd_alloc(&init_mm, dir, address); next = pgd_addr_end(addr, end);
if (!pmd) { err = remap_area_pmd(pgd, addr, next, phys_addr, prot);
err = -ENOMEM; if (err)
break;
}
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags)) {
err = -ENOMEM;
break; break;
} phys_addr += next - addr;
} while (pgd++, addr = next, addr != end);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment