csky: fixup CACHEV1 store instruction fast retire
authorGuo Ren <ren_guo@c-sky.com>
Tue, 8 Jan 2019 12:17:49 +0000 (20:17 +0800)
committerGuo Ren <ren_guo@c-sky.com>
Tue, 8 Jan 2019 15:42:42 +0000 (23:42 +0800)
For I/O access, 810/807 store instruction fast retire will cause wrong
primitive. For example:

stw (clear interrupt source)
stw (unmask interrupt controller)
enable interrupt

stw is fast retire instruction. When PC is run at enable interrupt
stage, the clear interrupt source hasn't finished. It will cause another
wrong irq-enter.

So use mb() to prevent above.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Cc: Lu Baoquan <lu.baoquan@intellif.com>
arch/csky/include/asm/io.h

index ecae6b358f95ffdfd041e5d6ea0d6c68a9e19bac..c1dfa9c10e36ccb1992991b5363b0ef31473e643 100644 (file)
@@ -15,6 +15,31 @@ extern void iounmap(void *addr);
 extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
                size_t size, unsigned long flags);
 
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.
+ *
+ * For CACHEV1 (807, 810), store instruction could fast retire, so we need
+ * another mb() to prevent st fast retire.
+ *
+ * For CACHEV2 (860), store instruction with PAGE_ATTR_NO_BUFFERABLE won't
+ * fast retire.
+ */
+#define readb(c)               ({ u8  __v = readb_relaxed(c); rmb(); __v; })
+#define readw(c)               ({ u16 __v = readw_relaxed(c); rmb(); __v; })
+#define readl(c)               ({ u32 __v = readl_relaxed(c); rmb(); __v; })
+
+#ifdef CONFIG_CPU_HAS_CACHEV2
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); })
+#else
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); mb(); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); mb(); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); mb(); })
+#endif
+
 #define ioremap_nocache(phy, sz)       ioremap(phy, sz)
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache