mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
[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
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user