On Mon, 19 Jan 2009 10:14:11 -0700, Russell King - ARM Linux <[email protected]> wrote:

On Mon, Jan 19, 2009 at 10:07:13AM -0700, Matt Gerassimoff wrote:
On Mon, 19 Jan 2009 09:13:58 -0700, Russell King - ARM Linux
<[email protected]> wrote:

>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);

Before this is even tested. I've went down this path. You will receive a
ton
of Bad PMD errors.  unmap_area_sections() and vunmap() don't play nice
together.
This type of solution will require changes to unmap_area_sections().

Okay, I've just lost interest in persuing this bug any further.

I mis-spoke, the changes required are in remap_area_sections().  They
are not doing proper manipulations to the pmd information.  If
remap_area_sections() is fixed, there will be no need for unmap_area_sections()
as vunmap() will do all the work as far as I can tell.

From that statement you just made, where does that leave us? This in my estimation is a MAJOR issue. If you need help testing this, I'll be happy to do so. It may be faster for you to create a simple kernel module that ioremap() on module init and iounmep() on module exit. Printing the returned virtual address from ioremap() on each load will yeild a higher and higher addresses until it returns a NULL pointer and kernel OOPS. I'm running on a at91sam9260 and it will fail on about 6 to 10
load/unload cycles of the kernel module.  So it happens pretty fast.

--
Matt
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to