2 * Re-map IO memory to kernel address space so that we can access it.
3 * This is needed for high PCI addresses that aren't mapped in the
4 * 640k-1MB IO memory area on PC's
6 * (C) Copyright 1995 1996 Linus Torvalds
8 #include <linux/vmalloc.h>
10 #include <linux/sched.h>
12 #include <linux/export.h>
13 #include <asm/cacheflush.h>
14 #include <asm/pgtable.h>
16 #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
17 int __read_mostly ioremap_pud_capable
;
18 int __read_mostly ioremap_pmd_capable
;
19 int __read_mostly ioremap_huge_disabled
;
21 static int __init
set_nohugeiomap(char *str
)
23 ioremap_huge_disabled
= 1;
26 early_param("nohugeiomap", set_nohugeiomap
);
28 void __init
ioremap_huge_init(void)
30 if (!ioremap_huge_disabled
) {
31 if (arch_ioremap_pud_supported())
32 ioremap_pud_capable
= 1;
33 if (arch_ioremap_pmd_supported())
34 ioremap_pmd_capable
= 1;
38 static inline int ioremap_pud_enabled(void)
40 return ioremap_pud_capable
;
43 static inline int ioremap_pmd_enabled(void)
45 return ioremap_pmd_capable
;
48 #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
49 static inline int ioremap_pud_enabled(void) { return 0; }
50 static inline int ioremap_pmd_enabled(void) { return 0; }
51 #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
53 static int ioremap_pte_range(pmd_t
*pmd
, unsigned long addr
,
54 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
59 pfn
= phys_addr
>> PAGE_SHIFT
;
60 pte
= pte_alloc_kernel(pmd
, addr
);
64 BUG_ON(!pte_none(*pte
));
65 set_pte_at(&init_mm
, addr
, pte
, pfn_pte(pfn
, prot
));
67 } while (pte
++, addr
+= PAGE_SIZE
, addr
!= end
);
71 static inline int ioremap_pmd_range(pud_t
*pud
, unsigned long addr
,
72 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
78 pmd
= pmd_alloc(&init_mm
, pud
, addr
);
82 next
= pmd_addr_end(addr
, end
);
83 if (ioremap_pte_range(pmd
, addr
, next
, phys_addr
+ addr
, prot
))
85 } while (pmd
++, addr
= next
, addr
!= end
);
89 static inline int ioremap_pud_range(pgd_t
*pgd
, unsigned long addr
,
90 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
96 pud
= pud_alloc(&init_mm
, pgd
, addr
);
100 next
= pud_addr_end(addr
, end
);
101 if (ioremap_pmd_range(pud
, addr
, next
, phys_addr
+ addr
, prot
))
103 } while (pud
++, addr
= next
, addr
!= end
);
107 int ioremap_page_range(unsigned long addr
,
108 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
119 pgd
= pgd_offset_k(addr
);
121 next
= pgd_addr_end(addr
, end
);
122 err
= ioremap_pud_range(pgd
, addr
, next
, phys_addr
+addr
, prot
);
125 } while (pgd
++, addr
= next
, addr
!= end
);
127 flush_cache_vmap(start
, end
);
131 EXPORT_SYMBOL_GPL(ioremap_page_range
);