aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/ioremap.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/ioremap.c')
-rw-r--r--arch/arm/mm/ioremap.c82
1 files changed, 52 insertions, 30 deletions
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index bdb248c4f55c..12c7ad215ce7 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -36,12 +36,6 @@
36#include <asm/mach/map.h> 36#include <asm/mach/map.h>
37#include "mm.h" 37#include "mm.h"
38 38
39/*
40 * Used by ioremap() and iounmap() code to mark (super)section-mapped
41 * I/O regions in vm_struct->flags field.
42 */
43#define VM_ARM_SECTION_MAPPING 0x80000000
44
45int ioremap_page(unsigned long virt, unsigned long phys, 39int ioremap_page(unsigned long virt, unsigned long phys,
46 const struct mem_type *mtype) 40 const struct mem_type *mtype)
47{ 41{
@@ -201,12 +195,6 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
201 if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) 195 if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
202 return NULL; 196 return NULL;
203 197
204 /*
205 * Don't allow RAM to be mapped - this causes problems with ARMv6+
206 */
207 if (WARN_ON(pfn_valid(pfn)))
208 return NULL;
209
210 type = get_mem_type(mtype); 198 type = get_mem_type(mtype);
211 if (!type) 199 if (!type)
212 return NULL; 200 return NULL;
@@ -216,6 +204,34 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
216 */ 204 */
217 size = PAGE_ALIGN(offset + size); 205 size = PAGE_ALIGN(offset + size);
218 206
207 /*
208 * Try to reuse one of the static mapping whenever possible.
209 */
210 read_lock(&vmlist_lock);
211 for (area = vmlist; area; area = area->next) {
212 if (!size || (sizeof(phys_addr_t) == 4 && pfn >= 0x100000))
213 break;
214 if (!(area->flags & VM_ARM_STATIC_MAPPING))
215 continue;
216 if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
217 continue;
218 if (__phys_to_pfn(area->phys_addr) > pfn ||
219 __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
220 continue;
221 /* we can drop the lock here as we know *area is static */
222 read_unlock(&vmlist_lock);
223 addr = (unsigned long)area->addr;
224 addr += __pfn_to_phys(pfn) - area->phys_addr;
225 return (void __iomem *) (offset + addr);
226 }
227 read_unlock(&vmlist_lock);
228
229 /*
230 * Don't allow RAM to be mapped - this causes problems with ARMv6+
231 */
232 if (WARN_ON(pfn_valid(pfn)))
233 return NULL;
234
219 area = get_vm_area_caller(size, VM_IOREMAP, caller); 235 area = get_vm_area_caller(size, VM_IOREMAP, caller);
220 if (!area) 236 if (!area)
221 return NULL; 237 return NULL;
@@ -313,28 +329,34 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
313void __iounmap(volatile void __iomem *io_addr) 329void __iounmap(volatile void __iomem *io_addr)
314{ 330{
315 void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); 331 void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
316#ifndef CONFIG_SMP 332 struct vm_struct *vm;
317 struct vm_struct **p, *tmp;
318 333
319 /* 334 read_lock(&vmlist_lock);
320 * If this is a section based mapping we need to handle it 335 for (vm = vmlist; vm; vm = vm->next) {
321 * specially as the VM subsystem does not know how to handle 336 if (vm->addr > addr)
322 * such a beast. We need the lock here b/c we need to clear 337 break;
323 * all the mappings before the area can be reclaimed 338 if (!(vm->flags & VM_IOREMAP))
324 * by someone else. 339 continue;
325 */ 340 /* If this is a static mapping we must leave it alone */
326 write_lock(&vmlist_lock); 341 if ((vm->flags & VM_ARM_STATIC_MAPPING) &&
327 for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { 342 (vm->addr <= addr) && (vm->addr + vm->size > addr)) {
328 if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { 343 read_unlock(&vmlist_lock);
329 if (tmp->flags & VM_ARM_SECTION_MAPPING) { 344 return;
330 unmap_area_sections((unsigned long)tmp->addr, 345 }
331 tmp->size); 346#ifndef CONFIG_SMP
332 } 347 /*
348 * If this is a section based mapping we need to handle it
349 * specially as the VM subsystem does not know how to handle
350 * such a beast.
351 */
352 if ((vm->addr == addr) &&
353 (vm->flags & VM_ARM_SECTION_MAPPING)) {
354 unmap_area_sections((unsigned long)vm->addr, vm->size);
333 break; 355 break;
334 } 356 }
335 }
336 write_unlock(&vmlist_lock);
337#endif 357#endif
358 }
359 read_unlock(&vmlist_lock);
338 360
339 vunmap(addr); 361 vunmap(addr);
340} 362}