diff options
Diffstat (limited to 'arch/arm/mm/ioremap.c')
-rw-r--r-- | arch/arm/mm/ioremap.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 12c7ad215ce..80632e8d753 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -58,7 +58,7 @@ void __check_kvm_seq(struct mm_struct *mm) | |||
58 | } while (seq != init_mm.context.kvm_seq); | 58 | } while (seq != init_mm.context.kvm_seq); |
59 | } | 59 | } |
60 | 60 | ||
61 | #ifndef CONFIG_SMP | 61 | #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) |
62 | /* | 62 | /* |
63 | * Section support is unsafe on SMP - If you iounmap and ioremap a region, | 63 | * Section support is unsafe on SMP - If you iounmap and ioremap a region, |
64 | * the other CPUs will not see this change until their next context switch. | 64 | * the other CPUs will not see this change until their next context switch. |
@@ -73,13 +73,16 @@ static void unmap_area_sections(unsigned long virt, unsigned long size) | |||
73 | { | 73 | { |
74 | unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1)); | 74 | unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1)); |
75 | pgd_t *pgd; | 75 | pgd_t *pgd; |
76 | pud_t *pud; | ||
77 | pmd_t *pmdp; | ||
76 | 78 | ||
77 | flush_cache_vunmap(addr, end); | 79 | flush_cache_vunmap(addr, end); |
78 | pgd = pgd_offset_k(addr); | 80 | pgd = pgd_offset_k(addr); |
81 | pud = pud_offset(pgd, addr); | ||
82 | pmdp = pmd_offset(pud, addr); | ||
79 | do { | 83 | do { |
80 | pmd_t pmd, *pmdp = pmd_offset(pgd, addr); | 84 | pmd_t pmd = *pmdp; |
81 | 85 | ||
82 | pmd = *pmdp; | ||
83 | if (!pmd_none(pmd)) { | 86 | if (!pmd_none(pmd)) { |
84 | /* | 87 | /* |
85 | * Clear the PMD from the page table, and | 88 | * Clear the PMD from the page table, and |
@@ -98,8 +101,8 @@ static void unmap_area_sections(unsigned long virt, unsigned long size) | |||
98 | pte_free_kernel(&init_mm, pmd_page_vaddr(pmd)); | 101 | pte_free_kernel(&init_mm, pmd_page_vaddr(pmd)); |
99 | } | 102 | } |
100 | 103 | ||
101 | addr += PGDIR_SIZE; | 104 | addr += PMD_SIZE; |
102 | pgd++; | 105 | pmdp += 2; |
103 | } while (addr < end); | 106 | } while (addr < end); |
104 | 107 | ||
105 | /* | 108 | /* |
@@ -118,6 +121,8 @@ remap_area_sections(unsigned long virt, unsigned long pfn, | |||
118 | { | 121 | { |
119 | unsigned long addr = virt, end = virt + size; | 122 | unsigned long addr = virt, end = virt + size; |
120 | pgd_t *pgd; | 123 | pgd_t *pgd; |
124 | pud_t *pud; | ||
125 | pmd_t *pmd; | ||
121 | 126 | ||
122 | /* | 127 | /* |
123 | * Remove and free any PTE-based mapping, and | 128 | * Remove and free any PTE-based mapping, and |
@@ -126,17 +131,17 @@ remap_area_sections(unsigned long virt, unsigned long pfn, | |||
126 | unmap_area_sections(virt, size); | 131 | unmap_area_sections(virt, size); |
127 | 132 | ||
128 | pgd = pgd_offset_k(addr); | 133 | pgd = pgd_offset_k(addr); |
134 | pud = pud_offset(pgd, addr); | ||
135 | pmd = pmd_offset(pud, addr); | ||
129 | do { | 136 | do { |
130 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
131 | |||
132 | pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); | 137 | pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); |
133 | pfn += SZ_1M >> PAGE_SHIFT; | 138 | pfn += SZ_1M >> PAGE_SHIFT; |
134 | pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); | 139 | pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); |
135 | pfn += SZ_1M >> PAGE_SHIFT; | 140 | pfn += SZ_1M >> PAGE_SHIFT; |
136 | flush_pmd_entry(pmd); | 141 | flush_pmd_entry(pmd); |
137 | 142 | ||
138 | addr += PGDIR_SIZE; | 143 | addr += PMD_SIZE; |
139 | pgd++; | 144 | pmd += 2; |
140 | } while (addr < end); | 145 | } while (addr < end); |
141 | 146 | ||
142 | return 0; | 147 | return 0; |
@@ -148,6 +153,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, | |||
148 | { | 153 | { |
149 | unsigned long addr = virt, end = virt + size; | 154 | unsigned long addr = virt, end = virt + size; |
150 | pgd_t *pgd; | 155 | pgd_t *pgd; |
156 | pud_t *pud; | ||
157 | pmd_t *pmd; | ||
151 | 158 | ||
152 | /* | 159 | /* |
153 | * Remove and free any PTE-based mapping, and | 160 | * Remove and free any PTE-based mapping, and |
@@ -156,6 +163,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, | |||
156 | unmap_area_sections(virt, size); | 163 | unmap_area_sections(virt, size); |
157 | 164 | ||
158 | pgd = pgd_offset_k(virt); | 165 | pgd = pgd_offset_k(virt); |
166 | pud = pud_offset(pgd, addr); | ||
167 | pmd = pmd_offset(pud, addr); | ||
159 | do { | 168 | do { |
160 | unsigned long super_pmd_val, i; | 169 | unsigned long super_pmd_val, i; |
161 | 170 | ||
@@ -164,14 +173,12 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, | |||
164 | super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; | 173 | super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; |
165 | 174 | ||
166 | for (i = 0; i < 8; i++) { | 175 | for (i = 0; i < 8; i++) { |
167 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
168 | |||
169 | pmd[0] = __pmd(super_pmd_val); | 176 | pmd[0] = __pmd(super_pmd_val); |
170 | pmd[1] = __pmd(super_pmd_val); | 177 | pmd[1] = __pmd(super_pmd_val); |
171 | flush_pmd_entry(pmd); | 178 | flush_pmd_entry(pmd); |
172 | 179 | ||
173 | addr += PGDIR_SIZE; | 180 | addr += PMD_SIZE; |
174 | pgd++; | 181 | pmd += 2; |
175 | } | 182 | } |
176 | 183 | ||
177 | pfn += SUPERSECTION_SIZE >> PAGE_SHIFT; | 184 | pfn += SUPERSECTION_SIZE >> PAGE_SHIFT; |
@@ -189,11 +196,13 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | |||
189 | unsigned long addr; | 196 | unsigned long addr; |
190 | struct vm_struct * area; | 197 | struct vm_struct * area; |
191 | 198 | ||
199 | #ifndef CONFIG_ARM_LPAE | ||
192 | /* | 200 | /* |
193 | * High mappings must be supersection aligned | 201 | * High mappings must be supersection aligned |
194 | */ | 202 | */ |
195 | if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) | 203 | if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) |
196 | return NULL; | 204 | return NULL; |
205 | #endif | ||
197 | 206 | ||
198 | type = get_mem_type(mtype); | 207 | type = get_mem_type(mtype); |
199 | if (!type) | 208 | if (!type) |
@@ -237,7 +246,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | |||
237 | return NULL; | 246 | return NULL; |
238 | addr = (unsigned long)area->addr; | 247 | addr = (unsigned long)area->addr; |
239 | 248 | ||
240 | #ifndef CONFIG_SMP | 249 | #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) |
241 | if (DOMAIN_IO == 0 && | 250 | if (DOMAIN_IO == 0 && |
242 | (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || | 251 | (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || |
243 | cpu_is_xsc3()) && pfn >= 0x100000 && | 252 | cpu_is_xsc3()) && pfn >= 0x100000 && |
@@ -343,7 +352,7 @@ void __iounmap(volatile void __iomem *io_addr) | |||
343 | read_unlock(&vmlist_lock); | 352 | read_unlock(&vmlist_lock); |
344 | return; | 353 | return; |
345 | } | 354 | } |
346 | #ifndef CONFIG_SMP | 355 | #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) |
347 | /* | 356 | /* |
348 | * If this is a section based mapping we need to handle it | 357 | * If this is a section based mapping we need to handle it |
349 | * specially as the VM subsystem does not know how to handle | 358 | * specially as the VM subsystem does not know how to handle |