static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end, phys_addr_t phys_addr, pgprot_t prot) { p4d_t *p4d; unsigned long next; phys_addr -= addr; p4d = p4d_alloc(&init_mm, pgd, addr); if (!p4d) return -ENOMEM; do { next = p4d_addr_end(addr, end); if (ioremap_p4d_enabled() && ((next - addr) == P4D_SIZE) && IS_ALIGNED(phys_addr + addr, P4D_SIZE)) { if (p4d_set_huge(p4d, phys_addr + addr, prot)) continue; } if (ioremap_pud_range(p4d, addr, next, phys_addr + addr, prot)) return -ENOMEM; } while (p4d++, addr = next, addr != end); return 0; }
int ioremap_page_range(unsigned long addr, unsigned long end, unsigned long phys_addr, pgprot_t prot) { pgd_t *pgd; unsigned long start; unsigned long next; int err; BUG_ON(addr >= end); start = addr; phys_addr -= addr; pgd = pgd_offset_k(addr); do { next = pgd_addr_end(addr, end); err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot); if (err) break; } while (pgd++, addr = next, addr != end); flush_cache_vmap(start, end); return err; }