Skip to content

Commit

Permalink
[ARM] Clean up ioremap code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Russell King authored and Russell King committed Dec 13, 2006
1 parent ad1ae2f commit da2c12a
Showing 1 changed file with 40 additions and 58 deletions.
98 changes: 40 additions & 58 deletions arch/arm/mm/ioremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

address &= ~PGDIR_MASK;
end = address + size;
unsigned long next;
pmd_t *pmd;
int ret = 0;

if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
pmd = pmd_alloc(&init_mm, pgd, addr);
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 {
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;
break;
}
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags)) {
err = -ENOMEM;
next = pgd_addr_end(addr, end);
err = remap_area_pmd(pgd, addr, next, phys_addr, prot);
if (err)
break;
}

address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
phys_addr += next - addr;
} while (pgd++, addr = next, addr != end);

return err;
}
Expand Down

0 comments on commit da2c12a

Please sign in to comment.