Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Tested-by: Matt Gerassimoff <mgeras@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Russell King and committed by
Russell King
24f11ec0 fb22d727

+2 -9
+2 -9
arch/arm/mm/ioremap.c
··· 138 138 */ 139 139 static void unmap_area_sections(unsigned long virt, unsigned long size) 140 140 { 141 - unsigned long addr = virt, end = virt + (size & ~SZ_1M); 141 + unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1)); 142 142 pgd_t *pgd; 143 143 144 144 flush_cache_vunmap(addr, end); ··· 337 337 void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); 338 338 #ifndef CONFIG_SMP 339 339 struct vm_struct **p, *tmp; 340 - #endif 341 - unsigned int section_mapping = 0; 342 340 343 - #ifndef CONFIG_SMP 344 341 /* 345 342 * If this is a section based mapping we need to handle it 346 343 * specially as the VM subsystem does not know how to handle ··· 349 352 for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { 350 353 if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { 351 354 if (tmp->flags & VM_ARM_SECTION_MAPPING) { 352 - *p = tmp->next; 353 355 unmap_area_sections((unsigned long)tmp->addr, 354 356 tmp->size); 355 - kfree(tmp); 356 - section_mapping = 1; 357 357 } 358 358 break; 359 359 } ··· 358 364 write_unlock(&vmlist_lock); 359 365 #endif 360 366 361 - if (!section_mapping) 362 - vunmap(addr); 367 + vunmap(addr); 363 368 } 364 369 EXPORT_SYMBOL(__iounmap);