[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:
parent
ad1ae2fe7f
commit
da2c12a279
1 changed files with 40 additions and 58 deletions
|
@ -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;
|
pmd = pmd_alloc(&init_mm, pgd, addr);
|
||||||
end = address + size;
|
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 {
|
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;
|
break;
|
||||||
}
|
phys_addr += next - addr;
|
||||||
if (remap_area_pmd(pmd, address, end - address,
|
} while (pgd++, addr = next, addr != end);
|
||||||
phys_addr + address, flags)) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
address = (address + PGDIR_SIZE) & PGDIR_MASK;
|
|
||||||
dir++;
|
|
||||||
} while (address && (address < end));
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue