MIPS: iomap: Use __mem_{read,write}{b,w,l} for MMIO
authorMarkos Chandras <markos.chandras@imgtec.com>
Wed, 2 Apr 2014 08:53:24 +0000 (09:53 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 24 Nov 2014 06:45:42 +0000 (07:45 +0100)
Using the __raw_{read,write}{b,w,l} functions to perform
repeatable MMIO could result in problems if the host bus
does not match the endianness of the PCI/ISA. This problem
is visible on big-endian SEAD3 configurations after commit
2925f6c0c7af32720dcbadc586463aeceb6baa22
"net: smc911x: use io{read,write}*_rep accessors". This effectively
moves away from using the __mem_* variants to __raw_* ones
and causes a kernel bug as follows:

Call Trace:
CPU 0 Unable to handle kernel paging request at virtual address 00000000,
epc == 00000000, ra == 8012b3b0
Oops[#1]:
Cpu 0
$ 0   : 00000000 00000065 00000000 00000004
$ 4   : 00000000 00000000 9a82dd60 00000000
$ 8   : 00000000 00000000 a00ae278 00000007
$12   : 0000000e 00000011 804c4228 ffff9411
$16   : 00000100 00000000 80560000 807fc6d0
$20   : 807fc8d0 807fcad0 807fbec0 00000100
$24   : 00009150 80109be0
$28   : 9a82c000 9a82dd28 00000001 8012b3b0
Hi    : 00000000
Lo    : 00000000
epc   : 00000000   (null)
    Not tainted
ra    : 8012b3b0 call_timer_fn.isra.39+0x24/0x84
Status: 10009503    KERNEL EXL IE
Cause : 00800808
BadVA : 00000000
PrId  : 00019c20 (MIPS M14Kc)
Modules linked in:
Process swapper (pid: 1, threadinfo=9a82c000, task=9a82ba18, tls=00000000)
Stack : 00000040 00000000 00000007 8056732c 80580000 00000001 9a82dd60 00200200
        80560000 8012b598 8056732c 80580000 00000001 00000000 9a82dd60 9a82dd60
        00000000 807fbd44 807fbd40 805664e0 0000000a 80800000 00000004 80125924
        0000fda0 000007f0 80000000 00000001 80800000 007f0000 00200140 80166338
        00000000 8100fda0 0000fda0 000007f0 80000000 00000001 80800000 007f0000
        ...
Call Trace:
[<8012b598>] run_timer_softirq+0x188/0x1f4
[<80125924>] __do_softirq+0xc4/0x18c
[<80166338>] handle_percpu_irq+0x54/0x84
[<80125aa4>] do_softirq+0x68/0x70
[<80103b50>] do_IRQ+0x18/0x28
[<80125d1c>] irq_exit+0x94/0xc0
[<80125aa4>] do_softirq+0x68/0x70
[<80102130>] ret_from_irq+0x0/0x4
[<80102130>] ret_from_irq+0x0/0x4
[<80125d1c>] irq_exit+0x94/0xc0
[<803165b0>] __bzero+0xd4/0x164
[<80346d0c>] mem32_serial_out+0x0/0x1c
[<8010d4ac>] free_init_pages+0x98/0xfc
[<80180a08>] free_hot_cold_page+0x2c/0x1c4
[<80180bd8>] __free_pages+0x38/0x98
[<8010d4a0>] free_init_pages+0x8c/0xfc
[<8010d4ac>] free_init_pages+0x98/0xfc
[<8049fb04>] kernel_init+0x28/0x15c
[<80147484>] schedule_tail+0x1c/0x60
[<8049fadc>] kernel_init+0x0/0x15c
[<80102178>] ret_from_kernel_thread+0x14/0x1c
[<8040a06f>] skb_pad+0xe7/0x13c

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: Steve Glendinning <steve.glendinning@shawell.net>
Cc: Ben Boeckel <mathstuf@gmail.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: Jeffrey Deans <Jeffrey.Deans@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6672/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/lib/iomap.c

index e3acb2dad33ad38585d2d8e195385af3e74f54d8..8e7e378ce51c323a34a8e9d0aa28a49b95ba90cd 100644 (file)
@@ -97,14 +97,14 @@ EXPORT_SYMBOL(iowrite32be);
 
 /*
  * These are the "repeat MMIO read/write" functions.
- * Note the "__raw" accesses, since we don't want to
- * convert to CPU byte order. We write in "IO byte
- * order" (we also don't have IO barriers).
+ * Note the "__mem" accesses, since we want to convert
+ * to CPU byte order if the host bus happens to not match the
+ * endianness of PCI/ISA (see mach-generic/mangle-port.h).
  */
 static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
 {
        while (--count >= 0) {
-               u8 data = __raw_readb(addr);
+               u8 data = __mem_readb(addr);
                *dst = data;
                dst++;
        }
@@ -113,7 +113,7 @@ static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
 static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
 {
        while (--count >= 0) {
-               u16 data = __raw_readw(addr);
+               u16 data = __mem_readw(addr);
                *dst = data;
                dst++;
        }
@@ -122,7 +122,7 @@ static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
 static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
 {
        while (--count >= 0) {
-               u32 data = __raw_readl(addr);
+               u32 data = __mem_readl(addr);
                *dst = data;
                dst++;
        }
@@ -131,7 +131,7 @@ static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
 static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
 {
        while (--count >= 0) {
-               __raw_writeb(*src, addr);
+               __mem_writeb(*src, addr);
                src++;
        }
 }
@@ -139,7 +139,7 @@ static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
 static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
 {
        while (--count >= 0) {
-               __raw_writew(*src, addr);
+               __mem_writew(*src, addr);
                src++;
        }
 }
@@ -147,7 +147,7 @@ static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
 static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
 {
        while (--count >= 0) {
-               __raw_writel(*src, addr);
+               __mem_writel(*src, addr);
                src++;
        }
 }