public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] ARM: asm: add readq/writeq methods
@ 2013-12-07 14:11 Matthias Mann
  2013-12-07 15:12 ` Måns Rullgård
  2013-12-07 15:25 ` Russell King - ARM Linux
  0 siblings, 2 replies; 4+ messages in thread
From: Matthias Mann @ 2013-12-07 14:11 UTC (permalink / raw)
  To: linux-arm-kernel

Add readq/writeq methods for 32 bit ARM to allow transfering 64 bit words over
PCIe as a single transfer.

Signed-off-by: Matthias Mann <m.mann@arkona-technologies.de>
---
This patch creates checkpatch warnings, but I used the style used for the
existing functions.
It is based on branch next/soc of the arm-soc tree.

 arch/arm/include/asm/io.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 3c597c2..0a8d015 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -94,6 +94,13 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
 		     : "r" (val));
 }
 
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+	asm volatile("strd %1, %0"
+		     : "+Qo" (*(volatile u64 __force *)addr)
+		     : "r" (val));
+}
+
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
 	u8 val;
@@ -112,6 +119,15 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
 	return val;
 }
 
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+	u64 val;
+	asm volatile("ldrd %1, %0"
+		     : "+Qo" (*(volatile u64 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+
 /*
  * Architecture ioremap implementation.
  */
@@ -293,18 +309,23 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 					__raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl(c)); __r; })
+#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+					__raw_readq(c)); __r; })
 
 #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 writeq_relaxed(v,c)	__raw_writeq((__force u64) cpu_to_le64(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 readq(c)		({ u64 __v = readq_relaxed(c); __iormb(); __v; })
 
 #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 writeq(v,c)		({ __iowmb(); writeq_relaxed(v,c); })
 
 #define readsb(p,d,l)		__raw_readsb(p,d,l)
 #define readsw(p,d,l)		__raw_readsw(p,d,l)
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH] ARM: asm: add readq/writeq methods
  2013-12-07 14:11 [PATCH] ARM: asm: add readq/writeq methods Matthias Mann
@ 2013-12-07 15:12 ` Måns Rullgård
  2013-12-07 15:20   ` Alexander Shiyan
  2013-12-07 15:25 ` Russell King - ARM Linux
  1 sibling, 1 reply; 4+ messages in thread
From: Måns Rullgård @ 2013-12-07 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Matthias Mann <M.Mann@arkona-technologies.de> writes:

> Add readq/writeq methods for 32 bit ARM to allow transfering 64 bit words over
> PCIe as a single transfer.
>
> Signed-off-by: Matthias Mann <m.mann@arkona-technologies.de>
> ---
> This patch creates checkpatch warnings, but I used the style used for the
> existing functions.
> It is based on branch next/soc of the arm-soc tree.
>
>  arch/arm/include/asm/io.h | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
> index 3c597c2..0a8d015 100644
> --- a/arch/arm/include/asm/io.h
> +++ b/arch/arm/include/asm/io.h
> @@ -94,6 +94,13 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
>  		     : "r" (val));
>  }
>
> +static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
> +{
> +	asm volatile("strd %1, %0"

Please use "strd %Q1, %R1, %0" here instead of relying on the
non-standard implicit second register operand.  Although current gcc
versions always allocate 64-bit values in even/odd register pairs, there
is no guarantee that this will always be the case (and llvm has no such
restriction).  In Thumb2, the registers do not need to be consecutive,
so implicitly adding 1 to the first register can silently result in
incorrect code.

For big endian, the register arguments need to be reversed.

> +		     : "+Qo" (*(volatile u64 __force *)addr)

The "o" constraint is not safe here.  The ldrd/strd instructions have a
limited offset range compared to ldr/str, so there is a risk that the
compiler-generated address is invalid.  Using "Q" forces the address to
be a single register, which is always safe.  This is why the 16-bit
versions of these functions use only "Q".  While this is slightly
suboptimal, there is unfortunately no constraint describing the
limitations of ldrd/strd addressing.

> +		     : "r" (val));
> +}

-- 
M?ns Rullg?rd
mans at mansr.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ARM: asm: add readq/writeq methods
  2013-12-07 15:12 ` Måns Rullgård
@ 2013-12-07 15:20   ` Alexander Shiyan
  0 siblings, 0 replies; 4+ messages in thread
From: Alexander Shiyan @ 2013-12-07 15:20 UTC (permalink / raw)
  To: linux-arm-kernel

> Matthias Mann <M.Mann@arkona-technologies.de> writes:
> 
> > Add readq/writeq methods for 32 bit ARM to allow transfering 64 bit words over
> > PCIe as a single transfer.
> >
> > Signed-off-by: Matthias Mann <m.mann@arkona-technologies.de>
> > ---
> > This patch creates checkpatch warnings, but I used the style used for the
> > existing functions.
> > It is based on branch next/soc of the arm-soc tree.
> >
> >  arch/arm/include/asm/io.h | 21 +++++++++++++++++++++
> >  1 file changed, 21 insertions(+)
> >
> > diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
> > index 3c597c2..0a8d015 100644
> > --- a/arch/arm/include/asm/io.h
> > +++ b/arch/arm/include/asm/io.h
> > @@ -94,6 +94,13 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
> >  		     : "r" (val));
> >  }
> >
> > +static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
> > +{
> > +	asm volatile("strd %1, %0"

Fixme, how this will work for ARMv4? Is this supported for systems above v5te
or I missed something?

---

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] ARM: asm: add readq/writeq methods
  2013-12-07 14:11 [PATCH] ARM: asm: add readq/writeq methods Matthias Mann
  2013-12-07 15:12 ` Måns Rullgård
@ 2013-12-07 15:25 ` Russell King - ARM Linux
  1 sibling, 0 replies; 4+ messages in thread
From: Russell King - ARM Linux @ 2013-12-07 15:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Dec 07, 2013 at 03:11:20PM +0100, Matthias Mann wrote:
> Add readq/writeq methods for 32 bit ARM to allow transfering 64 bit words over
> PCIe as a single transfer.

Since these asm instructions are not universally implemented, use of these
will lead to build time errors if a driver attempts to make use of these
on an ARM architecture which doesn't support it.

Hence, these need to be conditional - since they first appeared (iirc) in
ARMv5, then they should be conditional on

#if __LINUX_ARM_ARCH__ >= 5

However, there's another issue here.  The use of readq/writeq() is
controlled with various preprocessor or configuration symbols:

#if BITS_PER_LONG >= 64
#ifdef CONFIG_64BIT
#ifndef readq
#ifndef writeq

I much prefer the latter two, as it means drivers can individually
implement the lacking support in a way which is appropriate for the device
they're driving - which is especially important if reading a register has
side effects.  In other words, readq() and writeq() is not something that
can be provided by an arch where no 64-bit read/write IO instructions
exist.

This requires that where an architecture provides them, that they be
accompanied by these definitions:

#define readq readq
#define writeq writeq

to prevent the drivers own private definitions of these accessors
conflicting.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-12-07 15:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-07 14:11 [PATCH] ARM: asm: add readq/writeq methods Matthias Mann
2013-12-07 15:12 ` Måns Rullgård
2013-12-07 15:20   ` Alexander Shiyan
2013-12-07 15:25 ` Russell King - ARM Linux

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox