Merge tag 'asm-generic' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Apr 2018 16:15:48 +0000 (09:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Apr 2018 16:15:48 +0000 (09:15 -0700)
Pull asm-generic fixes from Arnd Bergmann:
 "I have one regression fix for a minor build problem after the
  architecture removal series, plus a rework of the barriers in the
  readl/writel functions, thanks to work by Sinan Kaya:

  This started from a discussion on the linuxpcc and rdma mailing
  lists[1]. To summarize, we decided that architectures are responsible
  to serialize readl() and writel() accesses on a device MMIO space
  relative to DMA performed by that device.

  This series provides a pessimistic implementation of that behavior for
  asm-generic/io.h, which is in turn used by a number of architectures
  (h8300, microblaze, nios2, openrisc, s390, sparc, um, unicore32, and
  xtensa). Some of those presumably need no extra barriers, or something
  weaker than rmb()/wmb(), and they are advised to override the new
  default for better performance.

  For inb()/outb(), the same barriers are used, but architectures might
  want to add another barrier to outb() here if that can guarantee
  non-posted behavior (some architectures can, others cannot do that).

  The readl_relaxed()/writel_relaxed() family of functions retains the
  existing behavior with no extra barriers"

[1] https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-March/170481.html

* tag 'asm-generic' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic:
  io: change writeX_relaxed() to remove barriers
  io: change readX_relaxed() to remove barriers
  dts: remove cris & metag dts hard link file
  io: change inX() to have their own IO barrier overrides
  io: change outX() to have their own IO barrier overrides
  io: define stronger ordering for the default writeX() implementation
  io: define stronger ordering for the default readX() implementation
  io: define several IO & PIO barrier types for the asm-generic version

1  2 
include/asm-generic/io.h

diff --combined include/asm-generic/io.h
index 04c4cc6fd820ae28b7a072d47e5f8d74acfe9f5e,f4a149403be9191d87324c288afe3c37c39cf6b8..66d1d45fa2e1c11dcf17231f0a32f883bb2c1a12
@@@ -1,4 -1,4 +1,4 @@@
 -/* Generic I/O port emulation, based on MN10300 code
 +/* Generic I/O port emulation.
   *
   * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
  #define mmiowb() do {} while (0)
  #endif
  
+ #ifndef __io_br
+ #define __io_br()      barrier()
+ #endif
+ /* prevent prefetching of coherent DMA data ahead of a dma-complete */
+ #ifndef __io_ar
+ #ifdef rmb
+ #define __io_ar()      rmb()
+ #else
+ #define __io_ar()      barrier()
+ #endif
+ #endif
+ /* flush writes to coherent DMA data before possibly triggering a DMA read */
+ #ifndef __io_bw
+ #ifdef wmb
+ #define __io_bw()      wmb()
+ #else
+ #define __io_bw()      barrier()
+ #endif
+ #endif
+ /* serialize device access against a spin_unlock, usually handled there. */
+ #ifndef __io_aw
+ #define __io_aw()      barrier()
+ #endif
+ #ifndef __io_pbw
+ #define __io_pbw()     __io_bw()
+ #endif
+ #ifndef __io_paw
+ #define __io_paw()     __io_aw()
+ #endif
+ #ifndef __io_pbr
+ #define __io_pbr()     __io_br()
+ #endif
+ #ifndef __io_par
+ #define __io_par()     __io_ar()
+ #endif
  /*
   * __raw_{read,write}{b,w,l,q}() access memory in native endianness.
   *
@@@ -110,7 -154,12 +154,12 @@@ static inline void __raw_writeq(u64 val
  #define readb readb
  static inline u8 readb(const volatile void __iomem *addr)
  {
-       return __raw_readb(addr);
+       u8 val;
+       __io_br();
+       val = __raw_readb(addr);
+       __io_ar();
+       return val;
  }
  #endif
  
  #define readw readw
  static inline u16 readw(const volatile void __iomem *addr)
  {
-       return __le16_to_cpu(__raw_readw(addr));
+       u16 val;
+       __io_br();
+       val = __le16_to_cpu(__raw_readw(addr));
+       __io_ar();
+       return val;
  }
  #endif
  
  #define readl readl
  static inline u32 readl(const volatile void __iomem *addr)
  {
-       return __le32_to_cpu(__raw_readl(addr));
+       u32 val;
+       __io_br();
+       val = __le32_to_cpu(__raw_readl(addr));
+       __io_ar();
+       return val;
  }
  #endif
  
  #define readq readq
  static inline u64 readq(const volatile void __iomem *addr)
  {
-       return __le64_to_cpu(__raw_readq(addr));
+       u64 val;
+       __io_br();
+       val = __le64_to_cpu(__raw_readq(addr));
+       __io_ar();
+       return val;
  }
  #endif
  #endif /* CONFIG_64BIT */
  #define writeb writeb
  static inline void writeb(u8 value, volatile void __iomem *addr)
  {
+       __io_bw();
        __raw_writeb(value, addr);
+       __io_aw();
  }
  #endif
  
  #define writew writew
  static inline void writew(u16 value, volatile void __iomem *addr)
  {
+       __io_bw();
        __raw_writew(cpu_to_le16(value), addr);
+       __io_aw();
  }
  #endif
  
  #define writel writel
  static inline void writel(u32 value, volatile void __iomem *addr)
  {
+       __io_bw();
        __raw_writel(__cpu_to_le32(value), addr);
+       __io_aw();
  }
  #endif
  
  #define writeq writeq
  static inline void writeq(u64 value, volatile void __iomem *addr)
  {
+       __io_bw();
        __raw_writeq(__cpu_to_le64(value), addr);
+       __io_aw();
  }
  #endif
  #endif /* CONFIG_64BIT */
   * accesses.
   */
  #ifndef readb_relaxed
- #define readb_relaxed readb
+ #define readb_relaxed readb_relaxed
+ static inline u8 readb_relaxed(const volatile void __iomem *addr)
+ {
+       return __raw_readb(addr);
+ }
  #endif
  
  #ifndef readw_relaxed
- #define readw_relaxed readw
+ #define readw_relaxed readw_relaxed
+ static inline u16 readw_relaxed(const volatile void __iomem *addr)
+ {
+       return __le16_to_cpu(__raw_readw(addr));
+ }
  #endif
  
  #ifndef readl_relaxed
- #define readl_relaxed readl
+ #define readl_relaxed readl_relaxed
+ static inline u32 readl_relaxed(const volatile void __iomem *addr)
+ {
+       return __le32_to_cpu(__raw_readl(addr));
+ }
  #endif
  
  #if defined(readq) && !defined(readq_relaxed)
- #define readq_relaxed readq
+ #define readq_relaxed readq_relaxed
+ static inline u64 readq_relaxed(const volatile void __iomem *addr)
+ {
+       return __le64_to_cpu(__raw_readq(addr));
+ }
  #endif
  
  #ifndef writeb_relaxed
- #define writeb_relaxed writeb
+ #define writeb_relaxed writeb_relaxed
+ static inline void writeb_relaxed(u8 value, volatile void __iomem *addr)
+ {
+       __raw_writeb(value, addr);
+ }
  #endif
  
  #ifndef writew_relaxed
- #define writew_relaxed writew
+ #define writew_relaxed writew_relaxed
+ static inline void writew_relaxed(u16 value, volatile void __iomem *addr)
+ {
+       __raw_writew(cpu_to_le16(value), addr);
+ }
  #endif
  
  #ifndef writel_relaxed
- #define writel_relaxed writel
+ #define writel_relaxed writel_relaxed
+ static inline void writel_relaxed(u32 value, volatile void __iomem *addr)
+ {
+       __raw_writel(__cpu_to_le32(value), addr);
+ }
  #endif
  
  #if defined(writeq) && !defined(writeq_relaxed)
- #define writeq_relaxed writeq
+ #define writeq_relaxed writeq_relaxed
+ static inline void writeq_relaxed(u64 value, volatile void __iomem *addr)
+ {
+       __raw_writeq(__cpu_to_le64(value), addr);
+ }
  #endif
  
  /*
@@@ -351,8 -455,6 +455,8 @@@ static inline void writesq(volatile voi
  #define IO_SPACE_LIMIT 0xffff
  #endif
  
 +#include <linux/logic_pio.h>
 +
  /*
   * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
   * implemented on hardware that needs an additional delay for I/O accesses to
  #define inb inb
  static inline u8 inb(unsigned long addr)
  {
-       return readb(PCI_IOBASE + addr);
+       u8 val;
+       __io_pbr();
+       val = __raw_readb(PCI_IOBASE + addr);
+       __io_par();
+       return val;
  }
  #endif
  
  #define inw inw
  static inline u16 inw(unsigned long addr)
  {
-       return readw(PCI_IOBASE + addr);
+       u16 val;
+       __io_pbr();
+       val = __le16_to_cpu(__raw_readw(PCI_IOBASE + addr));
+       __io_par();
+       return val;
  }
  #endif
  
  #define inl inl
  static inline u32 inl(unsigned long addr)
  {
-       return readl(PCI_IOBASE + addr);
+       u32 val;
+       __io_pbr();
+       val = __le32_to_cpu(__raw_readl(PCI_IOBASE + addr));
+       __io_par();
+       return val;
  }
  #endif
  
  #define outb outb
  static inline void outb(u8 value, unsigned long addr)
  {
-       writeb(value, PCI_IOBASE + addr);
+       __io_pbw();
+       __raw_writeb(value, PCI_IOBASE + addr);
+       __io_paw();
  }
  #endif
  
  #define outw outw
  static inline void outw(u16 value, unsigned long addr)
  {
-       writew(value, PCI_IOBASE + addr);
+       __io_pbw();
+       __raw_writew(cpu_to_le16(value), PCI_IOBASE + addr);
+       __io_paw();
  }
  #endif
  
  #define outl outl
  static inline void outl(u32 value, unsigned long addr)
  {
-       writel(value, PCI_IOBASE + addr);
+       __io_pbw();
+       __raw_writel(cpu_to_le32(value), PCI_IOBASE + addr);
+       __io_paw();
  }
  #endif
  
@@@ -854,16 -977,7 +979,16 @@@ static inline void __iomem *__ioremap(p
  }
  #endif
  
 +#ifndef iounmap
 +#define iounmap iounmap
 +
 +static inline void iounmap(void __iomem *addr)
 +{
 +}
 +#endif
 +#endif /* CONFIG_MMU */
  #ifndef ioremap_nocache
 +void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
  #define ioremap_nocache ioremap_nocache
  static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
  {
@@@ -895,13 -1009,22 +1020,13 @@@ static inline void __iomem *ioremap_wt(
  }
  #endif
  
 -#ifndef iounmap
 -#define iounmap iounmap
 -
 -static inline void iounmap(void __iomem *addr)
 -{
 -}
 -#endif
 -#endif /* CONFIG_MMU */
 -
  #ifdef CONFIG_HAS_IOPORT_MAP
  #ifndef CONFIG_GENERIC_IOMAP
  #ifndef ioport_map
  #define ioport_map ioport_map
  static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
  {
 -      return PCI_IOBASE + (port & IO_SPACE_LIMIT);
 +      return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
  }
  #endif