Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+2 −9
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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)
	write_unlock(&vmlist_lock);
	write_unlock(&vmlist_lock);
#endif
#endif


	if (!section_mapping)
	vunmap(addr);
	vunmap(addr);
}
}
EXPORT_SYMBOL(__iounmap);
EXPORT_SYMBOL(__iounmap);