Commit 08a3c4bc23e2b71191ed95d4fd3177c23660e34f

Authored by Greg Ungerer
Committed by David Woodhouse
1 parent f938bc563b

mtd: fix wrong usage of ioremap_nocache() in uclinux.c map driver

The uclinux.c mapping driver uses ioremap_nocache() to map its physical
mapping address to a system virtual address. Problem is that the region
it is mapping is not device memory. It is ordinary system RAM. On most
non-MMU systems this doesn't matter, and the mapping is always a 1:1
translation of the address. On paged memory systems on some architectures
the page table mappings are not compatible between normal RAM and device
memory.

If we want to use the uclinux.c mapping driver on real MMU enabled systems
we should be using the kernel virtual address that the mapping is at. For
architectures that support the traditional initrd they use phys_to_virt or
__va to convert the physical start initrd address to a kernel usable virtual
address. The uclinux filesystem mapping is even more restrictive than the
typical initrd, it always follows the kernels own bss section (so always in
directly mapped memory). Therefore we can use the usual phys_to_virt to
translate the physical start address to a virtual address.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

Showing 1 changed file with 9 additions and 6 deletions Side-by-side Diff

drivers/mtd/maps/uclinux.c
... ... @@ -67,10 +67,16 @@
67 67 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
68 68 (int) mapp->phys, (int) mapp->size);
69 69  
70   - mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
  70 + /*
  71 + * The filesystem is guaranteed to be in direct mapped memory. It is
  72 + * directly following the kernels own bss region. Following the same
  73 + * mechanism used by architectures setting up traditional initrds we
  74 + * use phys_to_virt to get the virtual address of its start.
  75 + */
  76 + mapp->virt = phys_to_virt(mapp->phys);
71 77  
72 78 if (mapp->virt == 0) {
73   - printk("uclinux[mtd]: ioremap_nocache() failed\n");
  79 + printk("uclinux[mtd]: no virtual mapping?\n");
74 80 return(-EIO);
75 81 }
76 82  
... ... @@ -79,7 +85,6 @@
79 85 mtd = do_map_probe("map_ram", mapp);
80 86 if (!mtd) {
81 87 printk("uclinux[mtd]: failed to find a mapping?\n");
82   - iounmap(mapp->virt);
83 88 return(-ENXIO);
84 89 }
85 90  
86 91  
... ... @@ -102,10 +107,8 @@
102 107 map_destroy(uclinux_ram_mtdinfo);
103 108 uclinux_ram_mtdinfo = NULL;
104 109 }
105   - if (uclinux_ram_map.virt) {
106   - iounmap((void *) uclinux_ram_map.virt);
  110 + if (uclinux_ram_map.virt)
107 111 uclinux_ram_map.virt = 0;
108   - }
109 112 }
110 113  
111 114 /****************************************************************************/