diff options
Diffstat (limited to 'recipes/linux/linux-omap-pm-2.6.28/ioremap-fix.patch')
-rw-r--r-- | recipes/linux/linux-omap-pm-2.6.28/ioremap-fix.patch | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-pm-2.6.28/ioremap-fix.patch b/recipes/linux/linux-omap-pm-2.6.28/ioremap-fix.patch new file mode 100644 index 0000000000..406138b04d --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.28/ioremap-fix.patch @@ -0,0 +1,75 @@ +From: Russell King <rmk@dyn-67.arm.linux.org.uk> +Date: Sun, 25 Jan 2009 17:36:34 +0000 (+0000) +Subject: [ARM] fix section-based ioremap +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fkhilman%2Flinux-omap-pm.git;a=commitdiff_plain;h=9ae635f00a568cf95dbd15fa2c50eaee0aa27d2a + +[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> +(cherry picked from commit 24f11ec001920f1cfaeeed8e8b55725d900bbb56) +--- + +diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c +index 18373f7..9f88dd3 100644 +--- a/arch/arm/mm/ioremap.c ++++ b/arch/arm/mm/ioremap.c +@@ -138,7 +138,7 @@ void __check_kvm_seq(struct mm_struct *mm) + */ + 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; + + 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); + #ifndef CONFIG_SMP + 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 + * 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) { + if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { + if (tmp->flags & VM_ARM_SECTION_MAPPING) { +- *p = tmp->next; + unmap_area_sections((unsigned long)tmp->addr, + tmp->size); +- kfree(tmp); +- section_mapping = 1; + } + break; + } +@@ -364,7 +358,6 @@ void __iounmap(volatile void __iomem *io_addr) + write_unlock(&vmlist_lock); + #endif + +- if (!section_mapping) +- vunmap(addr); ++ vunmap(addr); + } + EXPORT_SYMBOL(__iounmap); |