From patchwork Wed Jun 10 12:30:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King - ARM Linux X-Patchwork-Id: 6578991 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1B0129F3D1 for ; Wed, 10 Jun 2015 12:33:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B151A205EB for ; Wed, 10 Jun 2015 12:33:37 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 16454205EA for ; Wed, 10 Jun 2015 12:33:36 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z2fAC-0006db-1T; Wed, 10 Jun 2015 12:31:24 +0000 Received: from pandora.arm.linux.org.uk ([2001:4d48:ad52:3201:214:fdff:fe10:1be6]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Z2fA5-0006VK-Q5 for linux-arm-kernel@lists.infradead.org; Wed, 10 Jun 2015 12:31:19 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora-2014; h=Sender:In-Reply-To:Content-Type:MIME-Version:References:Message-ID:Subject:Cc:To:From:Date; bh=dR8aByXET6YLHp4lVEmMaOMndPsu+xFMJfY0e2d60Rs=; b=oc+w/QEEGnoSTmqEKBse+gWoG3hmuZb+j0Dho19T0WR3Jxy/LsEJNOwlgFnwaI85qNQSwpBm4zzOFhrDkLhZAVuR6PfGs1MyeTEC1aR8mBm3ZLC5v2gqo1WByiY2jBZi3e02AiKSVkvUTG1HTwr3Y5wXRK3l4Eitrcq73R4Mqo0=; Received: from n2100.arm.linux.org.uk ([2002:4e20:1eda:1:214:fdff:fe10:4f86]:38945) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:DHE-RSA-AES256-SHA:256) (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1Z2f9Y-00081o-LN; Wed, 10 Jun 2015 13:30:44 +0100 Received: from linux by n2100.arm.linux.org.uk with local (Exim 4.76) (envelope-from ) id 1Z2f9V-0007pY-5F; Wed, 10 Jun 2015 13:30:41 +0100 Date: Wed, 10 Jun 2015 13:30:40 +0100 From: Russell King - ARM Linux To: Will Deacon Subject: Re: Moan: usage of __iormb() and __iowmb() outside of asm/io.h Message-ID: <20150610123040.GN7557@n2100.arm.linux.org.uk> References: <20150608184701.GA7557@n2100.arm.linux.org.uk> <20150610111819.GC22973@arm.com> <20150610112433.GM7557@n2100.arm.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20150610112433.GM7557@n2100.arm.linux.org.uk> User-Agent: Mutt/1.5.23 (2014-03-12) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150610_053118_339969_072D6AE8 X-CRM114-Status: GOOD ( 19.70 ) X-Spam-Score: -0.1 (/) Cc: Tony Lindgren , Catalin Marinas , Sebastian Andrzej Siewior , Murali Karicheri , Ivan Khoronzhuk , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Wed, Jun 10, 2015 at 12:24:34PM +0100, Russell King - ARM Linux wrote: > On Wed, Jun 10, 2015 at 12:18:20PM +0100, Will Deacon wrote: > > I agree to removing these from view; we already have plenty of barrier > > macros and we don't want these to proliferate outside of the arch code. > > > > Any chance you could do a similar change for arm64, please (we have the > > same macros there)? > > Yes - as you're aware, removing them from sight does cause us to decend > into macro-hell in asm/io.h, but I think that's better than having people > get their grubby fingers on arch internal stuff they shouldn't be touching. Here's what I'm proposing for ARM. As I say, it's macro-hell... It's also not perfect yet (since the __LINUX_ARM_ARCH__ < 6 case isn't properly handled yet.) The down-side is that we end up with a load of __arm_(read|write)* functions, which people could start using. I _guess_ a solution to that would be to have these macros be used to generate inline functions with the correct accessor name as required. diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index addfb3dd095f..6566ef9f69f8 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -31,6 +31,16 @@ #include #include +/* IO barriers */ +#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE +#include +#define __iormb() rmb() +#define __iowmb() wmb() +#else +#define __iormb() do { } while (0) +#define __iowmb() do { } while (0) +#endif + /* * ISA I/O bus memory addresses are 1:1 with the physical address. */ @@ -56,6 +66,61 @@ void __raw_readsb(const volatile void __iomem *addr, void *data, int bytelen); void __raw_readsw(const volatile void __iomem *addr, void *data, int wordlen); void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen); +/* + * Macros used to define the raw IO accessors. + * This generates: + * __arm_read[bwl]() + * __arm_read[bwl]_rmb() + * __arm_read[bwl]_le() + * __arm_read[bwl]_be() + * __arm_read[bwl]_le_rmb() + * __arm_read[bwl]_be_rmb() + * __arm_write[bwl]() + * __arm_write[bwl]_rmb() + * __arm_write[bwl]_le() + * __arm_write[bwl]_be() + * __arm_write[bwl]_le_rmb() + * __arm_write[bwl]_be_rmb() + */ +#define DEFINE_IOR_OP(size, suffix, endian, instr, constraint, conv, barrier) \ +static inline u##size __arm_read##suffix(const volatile avoid __iomem *addr) \ +{ \ + endian##size val; \ + asm volatile(instr \ + : "=r" (val) \ + : constraint (*(volatile endian##size __force *)addr)); \ + barrier; \ + return conv(val); \ +} + +#define DEFINE_IOW_OP(size, suffix, endian, instr, constraint, conv, barrier) \ +static inline void __arm_write##suffix(u##size val, volatile void __iomem *addr) \ +{ \ + barrier; \ + asm volatile(instr \ + : : "r" (conv(val)), \ + constraint (*(volatile endian##size __force *)addr)); \ +} + +#define DEFINE_IOR_OP_B(size, suffix, endian, instr, constraint, conv) \ +DEFINE_IOR_OP(size, suffix, endian, instr, constraint, conv, ) \ +DEFINE_IOR_OP(size, suffix##_rmb, endian, instr, constraint, conv, __iormb()) + +#define DEFINE_IOW_OP_B(size, suffix, endian, instr, constraint, conv) \ +DEFINE_IOW_OP(size, suffix, endian, instr, constraint, conv, ) \ +DEFINE_IOW_OP(size, suffix##_wmb, endian, instr, constraint, conv, __iowmb()) + +#define DEFINE_IO_OP(size, suffix, rinstr, winstr, constraint) \ +DEFINE_IOR_OP_B(size, suffix, u, rinstr, constraint,) \ +DEFINE_IOW_OP_B(size, suffix, u, winstr, constraint,) + +#define DEFINE_IO_LE_OP(size, suffix, rinstr, winstr, constraint) \ +DEFINE_IO_OP(size, suffix, rinstr, winstr, constraint) \ +DEFINE_IOR_OP_B(size, suffix##_le, le, rinstr, constraint, cpu_to_le##size) \ +DEFINE_IOW_OP_B(size, suffix##_le, le, winstr, constraint, le##size##_to_cpu) \ +DEFINE_IOR_OP_B(size, suffix##_be, be, rinstr, constraint, cpu_to_be##size) \ +DEFINE_IOW_OP_B(size, suffix##_be, be, winstr, constraint, be##size##_to_cpu) + #if __LINUX_ARM_ARCH__ < 6 /* * Half-word accesses are problematic with RiscPC due to limitations of @@ -70,57 +135,30 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen); * writeback addressing modes as these incur a significant performance * overhead (the address generation must be emulated in software). */ -#define __raw_writew __raw_writew -static inline void __raw_writew(u16 val, volatile void __iomem *addr) -{ - asm volatile("strh %1, %0" - : : "Q" (*(volatile u16 __force *)addr), "r" (val)); -} +#define __raw_writew __arm_writew +#define __raw_readw __arm_readw +DEFINE_IO_LE_OP(16, w, "ldrh %0, %1", "strh %0, %1", "Q") -#define __raw_readw __raw_readw -static inline u16 __raw_readw(const volatile void __iomem *addr) -{ - u16 val; - asm volatile("ldrh %0, %1" - : "=r" (val) - : "Q" (*(volatile u16 __force *)addr)); - return val; -} #endif -#define __raw_writeb __raw_writeb -static inline void __raw_writeb(u8 val, volatile void __iomem *addr) -{ - asm volatile("strb %1, %0" - : : "Qo" (*(volatile u8 __force *)addr), "r" (val)); -} +#define __raw_writeb __arm_writeb +#define __raw_readb __arm_readb +DEFINE_IO_OP(8, b, "ldrb %0, %1", "strb %0, %1", "Qo") -#define __raw_writel __raw_writel -static inline void __raw_writel(u32 val, volatile void __iomem *addr) -{ - asm volatile("str %1, %0" - : : "Qo" (*(volatile u32 __force *)addr), "r" (val)); -} +#define __raw_writel __arm_writel +#define __raw_readl __arm_readl +DEFINE_IO_LE_OP(32, l, "ldr %0, %1", "str %0, %1", "Qo") -#define __raw_readb __raw_readb -static inline u8 __raw_readb(const volatile void __iomem *addr) -{ - u8 val; - asm volatile("ldrb %0, %1" - : "=r" (val) - : "Qo" (*(volatile u8 __force *)addr)); - return val; -} +#undef DEFINE_IO_OP +#undef DEFINE_IOW_OP +#undef DEFINE_IOW_OP_B +#undef DEFINE_IOR_OP +#undef DEFINE_IOR_OP_B +#undef DEFINE_IO_LE_OP -#define __raw_readl __raw_readl -static inline u32 __raw_readl(const volatile void __iomem *addr) -{ - u32 val; - asm volatile("ldr %0, %1" - : "=r" (val) - : "Qo" (*(volatile u32 __force *)addr)); - return val; -} +/* Don't let people use these as another barrier in their code. */ +#undef __iowmb +#undef __iormb /* * Architecture ioremap implementation. @@ -170,16 +208,6 @@ static inline void __iomem *__typesafe_io(unsigned long addr) #define IOMEM(x) ((void __force __iomem *)(x)) -/* IO barriers */ -#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE -#include -#define __iormb() rmb() -#define __iowmb() wmb() -#else -#define __iormb() do { } while (0) -#define __iowmb() do { } while (0) -#endif - /* PCI fixed i/o mapping */ #define PCI_IO_VIRT_BASE 0xfee00000 #define PCI_IOBASE ((void __iomem *)PCI_IO_VIRT_BASE) @@ -250,17 +278,13 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr); * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space. */ #ifdef __io -#define outb(v,p) ({ __iowmb(); __raw_writeb(v,__io(p)); }) -#define outw(v,p) ({ __iowmb(); __raw_writew((__force __u16) \ - cpu_to_le16(v),__io(p)); }) -#define outl(v,p) ({ __iowmb(); __raw_writel((__force __u32) \ - cpu_to_le32(v),__io(p)); }) - -#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __iormb(); __v; }) -#define inw(p) ({ __u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__io(p))); __iormb(); __v; }) -#define inl(p) ({ __u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__io(p))); __iormb(); __v; }) +#define outb(v,p) __arm_writeb_wmb(v,__io(p)) +#define outw(v,p) __arm_writew_le_wmb(v,__io(p)) +#define outl(v,p) __arm_writel_le_wmb(v,__io(p)) + +#define inb(p) __arm_readb_rmb(__io(p)) +#define inw(p) __arm_readw_le_rmb(__io(p)) +#define inl(p) __arm_readl_le_rmb(__io(p)) #define outsb(p,d,l) __raw_writesb(__io(p),d,l) #define outsw(p,d,l) __raw_writesw(__io(p),d,l) @@ -291,23 +315,21 @@ extern void _memset_io(volatile void __iomem *, int, size_t); * IO port primitives for more information. */ #ifndef readl -#define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; }) -#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ - __raw_readw(c)); __r; }) -#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ - __raw_readl(c)); __r; }) +#define readb_relaxed(c) __arm_readb(c) +#define readw_relaxed(c) __arm_readw_le(c) +#define readl_relaxed(c) __arm_readl_le(c) -#define writeb_relaxed(v,c) __raw_writeb(v,c) -#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c) -#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) +#define writeb_relaxed(v,c) __arm_writeb(v,c) +#define writew_relaxed(v,c) __arm_writew_le(v,c) +#define writel_relaxed(v,c) __arm_writel_le(v,c) -#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) -#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) -#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +#define readb(c) __arm_readb_rmb(c) +#define readw(c) __arm_readw_le_rmb(c) +#define readl(c) __arm_readl_le_rmb(c) -#define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) -#define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); }) -#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) +#define writeb(v,c) __arm_writeb_wmb(v,c) +#define writew(v,c) __arm_writew_le_wmb(v,c) +#define writel(v,c) __arm_writel_le_wmb(v,c) #define readsb(p,d,l) __raw_readsb(p,d,l) #define readsw(p,d,l) __raw_readsw(p,d,l) @@ -363,11 +385,11 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, /* * io{read,write}{16,32}be() macros */ -#define ioread16be(p) ({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) -#define ioread32be(p) ({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) +#define ioread16be(p) __arm_readw_be_rmb(p) +#define ioread32be(p) __arm_readl_be_rmb(p) -#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); }) -#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); }) +#define iowrite16be(v,p) __arm_writew_be_wmb(v,p) +#define iowrite32be(v,p) __arm_writel_be_wmb(v,p) #ifndef ioport_map #define ioport_map ioport_map