Commit 24f11ec0 authored by Russell King's avatar Russell King Committed by Russell King

[ARM] fix section-based ioremap

Tomi Valkeinen reports:
  Running with latest linux-omap kernel on OMAP3 SDP board, I have
  problem with iounmap(). It looks like iounmap() does not properly
  free large areas. Below is a test which fails for me in 6-7 loops.

	for (i = 0; i < 200; ++i) {
		vaddr = ioremap(paddr, size);
		if (!vaddr) {
			printk("couldn't ioremap\n");
			break;
		}
		iounmap(vaddr);
	}

The changes to vmalloc.c weren't reflected in the ARM ioremap
implementation.  Turns out the fix is rather simple.
Tested-by: default avatarTomi Valkeinen <tomi.valkeinen@nokia.com>
Tested-by: default avatarMatt Gerassimoff <mgeras@gmail.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent fb22d727
...@@ -138,7 +138,7 @@ void __check_kvm_seq(struct mm_struct *mm) ...@@ -138,7 +138,7 @@ void __check_kvm_seq(struct mm_struct *mm)
*/ */
static void unmap_area_sections(unsigned long virt, unsigned long size) static void unmap_area_sections(unsigned long virt, unsigned long size)
{ {
unsigned long addr = virt, end = virt + (size & ~SZ_1M); unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1));
pgd_t *pgd; pgd_t *pgd;
flush_cache_vunmap(addr, end); flush_cache_vunmap(addr, end);
...@@ -337,10 +337,7 @@ void __iounmap(volatile void __iomem *io_addr) ...@@ -337,10 +337,7 @@ void __iounmap(volatile void __iomem *io_addr)
void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
struct vm_struct **p, *tmp; struct vm_struct **p, *tmp;
#endif
unsigned int section_mapping = 0;
#ifndef CONFIG_SMP
/* /*
* If this is a section based mapping we need to handle it * If this is a section based mapping we need to handle it
* specially as the VM subsystem does not know how to handle * specially as the VM subsystem does not know how to handle
...@@ -352,11 +349,8 @@ void __iounmap(volatile void __iomem *io_addr) ...@@ -352,11 +349,8 @@ void __iounmap(volatile void __iomem *io_addr)
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
if (tmp->flags & VM_ARM_SECTION_MAPPING) { if (tmp->flags & VM_ARM_SECTION_MAPPING) {
*p = tmp->next;
unmap_area_sections((unsigned long)tmp->addr, unmap_area_sections((unsigned long)tmp->addr,
tmp->size); tmp->size);
kfree(tmp);
section_mapping = 1;
} }
break; break;
} }
...@@ -364,7 +358,6 @@ void __iounmap(volatile void __iomem *io_addr) ...@@ -364,7 +358,6 @@ void __iounmap(volatile void __iomem *io_addr)
write_unlock(&vmlist_lock); write_unlock(&vmlist_lock);
#endif #endif
if (!section_mapping) vunmap(addr);
vunmap(addr);
} }
EXPORT_SYMBOL(__iounmap); EXPORT_SYMBOL(__iounmap);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment