Commit 0a4c56c8 authored by Linus Torvalds's avatar Linus Torvalds

fsldma: fix very broken 32-bit ppc ioread64 functionality

Commit ef91bb19 ("kernel.h: Silence sparse warning in
lower_32_bits") caused new warnings to show in the fsldma driver, but
that commit was not to blame: it only exposed some very incorrect code
that tried to take the low 32 bits of an address.

That made no sense for multiple reasons, the most notable one being that
that code was intentionally limited to only 32-bit ppc builds, so "only
low 32 bits of an address" was completely nonsensical.  There were no
high bits to mask off to begin with.

But even more importantly fropm a correctness standpoint, turning the
address into an integer then caused the subsequent address arithmetic to
be completely wrong too, and the "+1" actually incremented the address
by one, rather than by four.

Which again was incorrect, since the code was reading two 32-bit values
and trying to make a 64-bit end result of it all.  Surprisingly, the
iowrite64() did not suffer from the same odd and incorrect model.

This code has never worked, but it's questionable whether anybody cared:
of the two users that actually read the 64-bit value (by way of some C
preprocessor hackery and eventually the 'get_cdar()' inline function),
one of them explicitly ignored the value, and the other one might just
happen to work despite the incorrect value being read.

This patch at least makes it not fail the build any more, and makes the
logic superficially sane.  Whether it makes any difference to the code
_working_ or not shall remain a mystery.
Compile-tested-by: default avatarGuenter Roeck <linux@roeck-us.net>
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e77aee13
...@@ -205,10 +205,10 @@ struct fsldma_chan { ...@@ -205,10 +205,10 @@ struct fsldma_chan {
#else #else
static u64 fsl_ioread64(const u64 __iomem *addr) static u64 fsl_ioread64(const u64 __iomem *addr)
{ {
u32 fsl_addr = lower_32_bits(addr); u32 val_lo = in_le32((u32 __iomem *)addr);
u64 fsl_addr_hi = (u64)in_le32((u32 *)(fsl_addr + 1)) << 32; u32 val_hi = in_le32((u32 __iomem *)addr + 1);
return fsl_addr_hi | in_le32((u32 *)fsl_addr); return ((u64)val_hi << 32) + val_lo;
} }
static void fsl_iowrite64(u64 val, u64 __iomem *addr) static void fsl_iowrite64(u64 val, u64 __iomem *addr)
...@@ -219,10 +219,10 @@ static void fsl_iowrite64(u64 val, u64 __iomem *addr) ...@@ -219,10 +219,10 @@ static void fsl_iowrite64(u64 val, u64 __iomem *addr)
static u64 fsl_ioread64be(const u64 __iomem *addr) static u64 fsl_ioread64be(const u64 __iomem *addr)
{ {
u32 fsl_addr = lower_32_bits(addr); u32 val_hi = in_be32((u32 __iomem *)addr);
u64 fsl_addr_hi = (u64)in_be32((u32 *)fsl_addr) << 32; u32 val_lo = in_be32((u32 __iomem *)addr + 1);
return fsl_addr_hi | in_be32((u32 *)(fsl_addr + 1)); return ((u64)val_hi << 32) + val_lo;
} }
static void fsl_iowrite64be(u64 val, u64 __iomem *addr) static void fsl_iowrite64be(u64 val, u64 __iomem *addr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment