aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/mm/ioremap.c84
1 files changed, 6 insertions, 78 deletions
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 247fde76aaed..fff08ae7b5ed 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -12,7 +12,7 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <asm/io.h> 15#include <linux/io.h>
16#include <asm/fixmap.h> 16#include <asm/fixmap.h>
17#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
18#include <asm/tlbflush.h> 18#include <asm/tlbflush.h>
@@ -21,82 +21,6 @@
21#define ISA_START_ADDRESS 0xa0000 21#define ISA_START_ADDRESS 0xa0000
22#define ISA_END_ADDRESS 0x100000 22#define ISA_END_ADDRESS 0x100000
23 23
24static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
25 unsigned long end, unsigned long phys_addr, unsigned long flags)
26{
27 pte_t *pte;
28 unsigned long pfn;
29
30 pfn = phys_addr >> PAGE_SHIFT;
31 pte = pte_alloc_kernel(pmd, addr);
32 if (!pte)
33 return -ENOMEM;
34 do {
35 BUG_ON(!pte_none(*pte));
36 set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW |
37 _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
38 pfn++;
39 } while (pte++, addr += PAGE_SIZE, addr != end);
40 return 0;
41}
42
43static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
44 unsigned long end, unsigned long phys_addr, unsigned long flags)
45{
46 pmd_t *pmd;
47 unsigned long next;
48
49 phys_addr -= addr;
50 pmd = pmd_alloc(&init_mm, pud, addr);
51 if (!pmd)
52 return -ENOMEM;
53 do {
54 next = pmd_addr_end(addr, end);
55 if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, flags))
56 return -ENOMEM;
57 } while (pmd++, addr = next, addr != end);
58 return 0;
59}
60
61static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
62 unsigned long end, unsigned long phys_addr, unsigned long flags)
63{
64 pud_t *pud;
65 unsigned long next;
66
67 phys_addr -= addr;
68 pud = pud_alloc(&init_mm, pgd, addr);
69 if (!pud)
70 return -ENOMEM;
71 do {
72 next = pud_addr_end(addr, end);
73 if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, flags))
74 return -ENOMEM;
75 } while (pud++, addr = next, addr != end);
76 return 0;
77}
78
79static int ioremap_page_range(unsigned long addr,
80 unsigned long end, unsigned long phys_addr, unsigned long flags)
81{
82 pgd_t *pgd;
83 unsigned long next;
84 int err;
85
86 BUG_ON(addr >= end);
87 flush_cache_all();
88 phys_addr -= addr;
89 pgd = pgd_offset_k(addr);
90 do {
91 next = pgd_addr_end(addr, end);
92 err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
93 if (err)
94 break;
95 } while (pgd++, addr = next, addr != end);
96 flush_tlb_all();
97 return err;
98}
99
100/* 24/*
101 * Generic mapping function (not visible outside): 25 * Generic mapping function (not visible outside):
102 */ 26 */
@@ -115,6 +39,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
115 void __iomem * addr; 39 void __iomem * addr;
116 struct vm_struct * area; 40 struct vm_struct * area;
117 unsigned long offset, last_addr; 41 unsigned long offset, last_addr;
42 pgprot_t prot;
118 43
119 /* Don't allow wraparound or zero size */ 44 /* Don't allow wraparound or zero size */
120 last_addr = phys_addr + size - 1; 45 last_addr = phys_addr + size - 1;
@@ -142,6 +67,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
142 return NULL; 67 return NULL;
143 } 68 }
144 69
70 prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
71 | _PAGE_ACCESSED | flags);
72
145 /* 73 /*
146 * Mappings have to be page-aligned 74 * Mappings have to be page-aligned
147 */ 75 */
@@ -158,7 +86,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
158 area->phys_addr = phys_addr; 86 area->phys_addr = phys_addr;
159 addr = (void __iomem *) area->addr; 87 addr = (void __iomem *) area->addr;
160 if (ioremap_page_range((unsigned long) addr, 88 if (ioremap_page_range((unsigned long) addr,
161 (unsigned long) addr + size, phys_addr, flags)) { 89 (unsigned long) addr + size, phys_addr, prot)) {
162 vunmap((void __force *) addr); 90 vunmap((void __force *) addr);
163 return NULL; 91 return NULL;
164 } 92 }