Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: Add missing io barriers to io{read,write}{16,32}be()

While reviewing a different change to asm-generic/io.h Arnd spotted that
ARC ioread32 and ioread32be both of which come from asm-generic versions
are not symmetrical in terms of calling the io barriers.

generic ioread32 -> ARC readl() [ has barriers]
generic ioread32be -> __be32_to_cpu(__raw_readl()) [ lacks barriers]

While generic ioread32be is being remediated to call readl(), that involves
a swab32(), causing double swaps on ioread32be() on Big Endian systems.

So provide our versions of big endian IO accessors to ensure io barrier
calls while also keeping them optimal

Suggested-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: stable@vger.kernel.org [4.2+]
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>

+18 -9
+18 -9
arch/arc/include/asm/io.h
··· 13 13 #include <asm/byteorder.h> 14 14 #include <asm/page.h> 15 15 16 + #ifdef CONFIG_ISA_ARCV2 17 + #include <asm/barrier.h> 18 + #define __iormb() rmb() 19 + #define __iowmb() wmb() 20 + #else 21 + #define __iormb() do { } while (0) 22 + #define __iowmb() do { } while (0) 23 + #endif 24 + 16 25 extern void __iomem *ioremap(phys_addr_t paddr, unsigned long size); 17 26 extern void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size, 18 27 unsigned long flags); ··· 39 30 #define ioremap_nocache(phy, sz) ioremap(phy, sz) 40 31 #define ioremap_wc(phy, sz) ioremap(phy, sz) 41 32 #define ioremap_wt(phy, sz) ioremap(phy, sz) 33 + 34 + /* 35 + * io{read,write}{16,32}be() macros 36 + */ 37 + #define ioread16be(p) ({ u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) 38 + #define ioread32be(p) ({ u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) 39 + 40 + #define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); }) 41 + #define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); }) 42 42 43 43 /* Change struct page to physical address */ 44 44 #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) ··· 125 107 : "memory"); 126 108 127 109 } 128 - 129 - #ifdef CONFIG_ISA_ARCV2 130 - #include <asm/barrier.h> 131 - #define __iormb() rmb() 132 - #define __iowmb() wmb() 133 - #else 134 - #define __iormb() do { } while (0) 135 - #define __iowmb() do { } while (0) 136 - #endif 137 110 138 111 /* 139 112 * MMIO can also get buffered/optimized in micro-arch, so barriers needed