Re: ioremap()/iounmap() problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 19 Jan 2009 10:14:11 -0700, Russell King - ARM Linux <linux@xxxxxxxxxxxxxxxx> 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
<linux@xxxxxxxxxxxxxxxx> 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux