Skip to contentSkip to conversation

Fix endianness of generic I/O accessors

PATCH RESEND Superseded Will Deacon 5 participants 17 messages Oct 17, 2012 – Oct 28, 2012

Subsystems (5)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Fix endianness of generic I/O accessors

Hello,

This is a resend of the patches I originally sent a while back:

http://marc.info/?l=linux-kernel&m=133552356617938&w=2

There was some loose conclusion then that documentation needed to be updated, which I didn't get round to doing. However, after discussion with Ben at LPC (following his `Big and Little Endian inside/out' presentation), he encouraged me to resend the patches anyway.

So here they are. I also included two extra patches to fix the MMC and ethernet drivers used on the ARM64 model, which is where I came across this issue in the first place.

Comments welcome,

Will

Big endian is not dead -- it just smells funny.

Will Deacon (4):
asm-generic: io: remove {read,write} string functions
asm-generic: io: don't perform swab during {in,out} string functions
mmc: mmci: use io{read,write}*_rep accessors instead of string
functions
net: smc91x: use io{read,write}*_rep accessors instead of string
functions

 drivers/mmc/host/mmci.c            |    8 +++---
 drivers/net/ethernet/smsc/smc91x.h |   20 ++++++++--------
 include/asm-generic/io.h           |   42 +++++------------------------------
 3 files changed, 20 insertions(+), 50 deletions(-)
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH RESEND 1/4 asm-generic: io: remove {read,write} string functions

The {read,write}s{b,w,l} functions are not defined across all architectures and therefore shouldn't be used by portable drivers. We should encourage driver writers to use the io{read,write}{8,16,32}_rep functions instead.

This patch removes the {read,write} string functions for the generic IO header as they have no place in a new architecture port.

Cc Arnd Bergmann <[email protected]>
Cc Mike Frysinger <[email protected]>
Cc Ben Herrenschmidt <[email protected]>
---
 include/asm-generic/io.h |   30 ------------------------------
 1 files changed, 0 insertions(+), 30 deletions(-)
include/asm-generic/io.h +0 -30
index 448303b..3607921 100644
@@ -217,36 +217,6 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 }
 #endif
 
-static inline void readsl(const void __iomem *addr, void *buf, int len)
-{
-	insl(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void readsw(const void __iomem *addr, void *buf, int len)
-{
-	insw(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void readsb(const void __iomem *addr, void *buf, int len)
-{
-	insb(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesl(const void __iomem *addr, const void *buf, int len)
-{
-	outsl(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesw(const void __iomem *addr, const void *buf, int len)
-{
-	outsw(addr - PCI_IOBASE, buf, len);
-}
-
-static inline void writesb(const void __iomem *addr, const void *buf, int len)
-{
-	outsb(addr - PCI_IOBASE, buf, len);
-}
-
 #ifndef CONFIG_GENERIC_IOMAP
 #define ioread8(addr)		readb(addr)
 #define ioread16(addr)		readw(addr)
Signature · 1 line
1.7.4.1
maintainer Acked-by on v1 1/4
#2 lore raw

Re: [RESEND PATCH 1/4] asm-generic: io: remove {read,write} string functions

Quoted 5 lines · Will Deacon

The {read,write}s{b,w,l} functions are not defined across all architectures and therefore shouldn't be used by portable drivers. We should encourage driver writers to use the io{read,write}{8,16,32}_rep functions instead.

Quoted 7 lines

This patch removes the {read,write} string functions for the generic IO header as they have no place in a new architecture port.

Cc Arnd Bergmann <[email protected]>
Cc Mike Frysinger <[email protected]>
Cc Ben Herrenschmidt <[email protected]>

What should we do with the series? I can take them through the asm-generic tree if you like, or we can let Catalin take them through the arm64 tree.

Arnd

#3 lore raw

Re: [RESEND PATCH 1/4] asm-generic: io: remove {read,write} string functions

Quoted 9 lines · Arnd Bergmann
Quoted 8 lines · Will Deacon

The {read,write}s{b,w,l} functions are not defined across all architectures and therefore shouldn't be used by portable drivers. We should encourage driver writers to use the io{read,write}{8,16,32}_rep functions instead.

This patch removes the {read,write} string functions for the generic IO header as they have no place in a new architecture port.

Quoted 6 lines
Quoted 4 lines
Cc Arnd Bergmann <[email protected]>
Cc Mike Frysinger <[email protected]>
Cc Ben Herrenschmidt <[email protected]>

Cheers Arnd!

Quoted 2 lines

What should we do with the series? I can take them through the asm-generic tree if you like, or we can let Catalin take them through the arm64 tree.

Can you take patch 2/4 via asm-generic please? I'll respin the rest of the series and try and update some more drivers in the process so that the removal of the generic stream functions doesn't cause breakage for drivers that aren't arch-specific already.

Thanks,

Will

#4 lore raw

PATCH RESEND 2/4 asm-generic: io: don't perform swab during {in,out} string functions

In reply to Will Deacon

The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order.

This patch fixes the generic IO header so that {in,out}s{b,w,l} call the __raw_{read,write} functions directly rather than going via the endian-correcting accessors.

---
 include/asm-generic/io.h |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
include/asm-generic/io.h +6 -6
index 3607921..403b861 100644
@@ -148,7 +148,7 @@ static inline void insb(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u8 *buf = buffer;
 		do {
-			u8 x = inb(addr);
+			u8 x = __raw_readb(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -161,7 +161,7 @@ static inline void insw(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u16 *buf = buffer;
 		do {
-			u16 x = inw(addr);
+			u16 x = __raw_readw(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -174,7 +174,7 @@ static inline void insl(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u32 *buf = buffer;
 		do {
-			u32 x = inl(addr);
+			u32 x = __raw_readl(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -187,7 +187,7 @@ static inline void outsb(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u8 *buf = buffer;
 		do {
-			outb(*buf++, addr);
+			__raw_writeb(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
@@ -199,7 +199,7 @@ static inline void outsw(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u16 *buf = buffer;
 		do {
-			outw(*buf++, addr);
+			__raw_writew(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
@@ -211,7 +211,7 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u32 *buf = buffer;
 		do {
-			outl(*buf++, addr);
+			__raw_writel(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
Signature · 1 line
1.7.4.1
#5 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Quoted 3 lines · Will Deacon

The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order.

Euh?

They transfer a stream of bytes between memory and PCI/ISA I/O space by reading from/writing to a single I/O port of width 8, 16, or 32 bits. On big endian machines, I/O port accesses may need to be swapped.

Quoted 3 lines

This patch fixes the generic IO header so that {in,out}s{b,w,l} call the __raw_{read,write} functions directly rather than going via the endian-correcting accessors.

Furthermore __raw_*() has different semantics besides endianness, like ordering barriers. So you can't just change one for the other.

include/asm-generic/io.h static inline void insb(unsigned long addr, void *buffer, int count)

Quoted 13 lines
---
 include/asm-generic/io.h |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
include/asm-generic/io.h +0 -0
index 3607921..403b861 100644
@@ -148,7 +148,7 @@ static inline void insb(unsigned long addr, void *buffer, int count)

The "addr" parameter is actually a misnomer. Probably it should be "port". Oops, inb() and friends also use "addr".

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#6 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Quoted 6 lines · Geert Uytterhoeven
Quoted 3 lines · Will Deacon

The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order.

Euh?

Will is perfectly right :-)

Quoted 3 lines

They transfer a stream of bytes between memory and PCI/ISA I/O space by reading from/writing to a single I/O port of width 8, 16, or 32 bits. On big endian machines, I/O port accesses may need to be swapped.

No. Not for streams. I suggest you watch the recording of my Plumbers talk :-)

The sort story is that endianness is not a property of the IO port but of the information that transit through it. If you're just going to copy it into memory, you want to preserve it's format and so do not byteswap.

The byteswap we do on standard accessors is a "helper" because we assume that underneath those IO ports are registers that are Little Endian. But when using one as a window to a byte stream, we must not arbitrarily swap the byte stream. We copy it as-is to memory, and then one can work at interpreting the various fields that might or might not be present in that stream with the appropriate accessors for memory accesses.

You will notice that all our stream IO functions are similarly non-swapping on powerpc.

Quoted 6 lines
Quoted 3 lines

This patch fixes the generic IO header so that {in,out}s{b,w,l} call the __raw_{read,write} functions directly rather than going via the endian-correcting accessors.

Furthermore __raw_*() has different semantics besides endianness, like ordering barriers. So you can't just change one for the other.

This is asm-generic. If you need barriers, implement your own. As far as I can tell, Will is perfectly correct.

Cheers,
Ben.

Quoted 27 lines

include/asm-generic/io.h static inline void insb(unsigned long addr, void *buffer, int count)

Quoted 13 lines
---
 include/asm-generic/io.h |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
include/asm-generic/io.h +0 -0
index 3607921..403b861 100644
@@ -148,7 +148,7 @@ static inline void insb(unsigned long addr, void *buffer, int count)

The "addr" parameter is actually a misnomer. Probably it should be "port". Oops, inb() and friends also use "addr".

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#7 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Hi Ben,

Quoted 8 lines · Benjamin Herrenschmidt
Quoted 6 lines · Geert Uytterhoeven
Quoted 3 lines · Will Deacon

The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order.

Euh?

Quoted 8 lines

Will is perfectly right :-)

Quoted 3 lines

They transfer a stream of bytes between memory and PCI/ISA I/O space by reading from/writing to a single I/O port of width 8, 16, or 32 bits. On big endian machines, I/O port accesses may need to be swapped.

No. Not for streams. I suggest you watch the recording of my Plumbers talk :-)

I will. But as email text on lkml is easier to refer to than videos, I will continue below,
so yo can refute me in plain text ;-)

Quoted 10 lines

The sort story is that endianness is not a property of the IO port but of the information that transit through it. If you're just going to copy it into memory, you want to preserve it's format and so do not byteswap.

The byteswap we do on standard accessors is a "helper" because we assume that underneath those IO ports are registers that are Little Endian. But when using one as a window to a byte stream, we must not arbitrarily swap the byte stream. We copy it as-is to memory, and then one can work at interpreting the various fields that might or might not be present in that stream with the appropriate accessors for memory accesses.

So assume you have the bytestream "Hello, world!\n" in memory on the PCI device.I.e.

00000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a |Hello, world!.|

You want to copy it to system RAM using readsl(), which does:

               u32 *buf = buffer;
               do {
                       u32 x = __raw_readl(addr + PCI_IOBASE);
                       *buf++ = x;
                } while (--count);

On little endian, the first __raw_readl() should return "0x6c6c6548", so it is stored correctly by "*buf = x ".
On big endian, the first __raw_readl() should return "0x48656c6c" instead, else it's stored incorrectly by "*buf = x ".
But the PCI bus is little endian, so I expect __raw_readl() would return "0x6c6c6548", and thus needs swapping?

On m68k (classic with MMU), the situation is a bit more complicated, as some ISA (or PCMCIA) busses are physically wired swapped. But inw() and insw() always do either both swapping, or both no swapping. The state of support for ISA drivers is a bit vague, though.

Now, on m68k without MMU, inw() doesn't do swapping, but insw() does. This agrees more or less with you and Will, except that the bus seems to be physically swapped?

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#8 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Quoted 26 lines · Geert Uytterhoeven
Quoted 10 lines · Benjamin Herrenschmidt

The sort story is that endianness is not a property of the IO port but of the information that transit through it. If you're just going to copy it into memory, you want to preserve it's format and so do not byteswap.

The byteswap we do on standard accessors is a "helper" because we assume that underneath those IO ports are registers that are Little Endian. But when using one as a window to a byte stream, we must not arbitrarily swap the byte stream. We copy it as-is to memory, and then one can work at interpreting the various fields that might or might not be present in that stream with the appropriate accessors for memory accesses.

So assume you have the bytestream "Hello, world!\n" in memory on the PCI device.I.e.

00000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a |Hello, world!.|

You want to copy it to system RAM using readsl(), which does:

               u32 *buf = buffer;
               do {
                       u32 x = __raw_readl(addr + PCI_IOBASE);
                       *buf++ = x;
                } while (--count);
Quoted 4 lines

On little endian, the first __raw_readl() should return "0x6c6c6548", so it is stored correctly by "*buf = x ".
On big endian, the first __raw_readl() should return "0x48656c6c" instead, else it's stored incorrectly by "*buf = x ".

So far so good...

Quoted 2 lines

But the PCI bus is little endian, so I expect __raw_readl() would return "0x6c6c6548", and thus needs swapping?

I think this would only happen if your busses are wired swapped, in which case you'll have to handle this in your arch code because reading from a device and then writing to memory will end up with the data in the wrong order (the data stream won't be affected by passing through the CPU).

Will

#9 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

In reply to Geert Uytterhoeven
Quoted 7 lines · Geert Uytterhoeven

So assume you have the bytestream "Hello, world!\n" in memory on the PCI device.I.e.

00000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a |Hello, world!.|

You want to copy it to system RAM using readsl(), which does:

Quoted 8 lines
               u32 *buf = buffer;
               do {
                       u32 x = __raw_readl(addr + PCI_IOBASE);
                       *buf++ = x;
                } while (--count);

On little endian, the first __raw_readl() should return "0x6c6c6548", so it is stored correctly by "*buf = x ".

Right.

Quoted 4 lines

On big endian, the first __raw_readl() should return "0x48656c6c" instead, else it's stored incorrectly by "*buf = x ".
But the PCI bus is little endian, so I expect __raw_readl() would return "0x6c6c6548", and thus needs swapping?

No. The PCI bus will return 0x48656c6c.

This is due to how the PCI bus is wired to the CPU bus, which is called "byte address invariant". When doing a read of your byte 0, the CPU will effectively read 0 with byte enables picking 48. Since the CPU wants the first byte in the MSB, the bus must be wired up to the CPU such that the MSB is the first byte in address order.

This is how a BE CPU is normally wired to a LE bus. The fact that a register needs to be swapped comes from the fact that the device will put the MSB in the higher address byte, which then corresponds to the LSB on the BE CPU -> needs swapping.

But for a byte stream, as you can see, no swapping is required.

To some extent, it looks as if the wiring is byte swapped, in order to provide the byte address invariance (and thus causes registers to look byteswapped) but it's really not, it's just a convention.

Quoted 4 lines

On m68k (classic with MMU), the situation is a bit more complicated, as some ISA (or PCMCIA) busses are physically wired swapped. But inw() and insw() always do either both swapping, or both no swapping. The state of support for ISA drivers is a bit vague, though.

Then something is horribly wrong in those m68k setups :-) Either in the way the busses are wired or in your implementation of either inw or insw.

Quoted 3 lines

Now, on m68k without MMU, inw() doesn't do swapping, but insw() does. This agrees more or less with you and Will, except that the bus seems to be physically swapped?

Yeah that's possible. In the early days people incorrectly thought it would be smart to do that, thus avoiding a byteswap for register accesses .... and causing all data (DMA or FIFO) to be all backward.

That's for example why the disks in the Tivo are byteswapped 16-bit by 16-bit on the platter (ie, all the data is).

I wouldn't be surprised if some 68k suffered from similar HW designer stupidity.

But the "proper" generic rule is byte address invariance, and that implies swap on register access and no swap on byte streams.

Cheers,
Ben.

Quoted 14 lines

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#10 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Hi Ben,

Quoted 24 lines · Benjamin Herrenschmidt
Quoted 7 lines · Geert Uytterhoeven

So assume you have the bytestream "Hello, world!\n" in memory on the PCI device.I.e.

00000000 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a |Hello, world!.|

You want to copy it to system RAM using readsl(), which does:

Quoted 8 lines
               u32 *buf = buffer;
               do {
                       u32 x = __raw_readl(addr + PCI_IOBASE);
                       *buf++ = x;
                } while (--count);

On little endian, the first __raw_readl() should return "0x6c6c6548", so it is stored correctly by "*buf = x ".

Right.

Quoted 4 lines

On big endian, the first __raw_readl() should return "0x48656c6c" instead, else it's stored incorrectly by "*buf = x ".
But the PCI bus is little endian, so I expect __raw_readl() would return "0x6c6c6548", and thus needs swapping?

Quoted 7 lines

No. The PCI bus will return 0x48656c6c.

This is due to how the PCI bus is wired to the CPU bus, which is called "byte address invariant". When doing a read of your byte 0, the CPU will effectively read 0 with byte enables picking 48. Since the CPU wants the first byte in the MSB, the bus must be wired up to the CPU such that the MSB is the first byte in address order.

According to
https://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/WritingPCIDrivers/endianness/endianness.html

"Byte-invariant addressing is a property of the bus bridge itself."

and

"From the software designer’s perspective, this means that the hardware does not byte swap the data. However, from the hardware designer’s perspective, the hardware must byte swap all data."

So this depends on a correct hardware implementation in the PCI host bridge?

Quoted 11 lines

This is how a BE CPU is normally wired to a LE bus. The fact that a register needs to be swapped comes from the fact that the device will put the MSB in the higher address byte, which then corresponds to the LSB on the BE CPU -> needs swapping.

But for a byte stream, as you can see, no swapping is required.

To some extent, it looks as if the wiring is byte swapped, in order to provide the byte address invariance (and thus causes registers to look byteswapped) but it's really not, it's just a convention.

Quoted 8 lines
Quoted 4 lines

On m68k (classic with MMU), the situation is a bit more complicated, as some ISA (or PCMCIA) busses are physically wired swapped. But inw() and insw() always do either both swapping, or both no swapping. The state of support for ISA drivers is a bit vague, though.

Then something is horribly wrong in those m68k setups :-) Either in the way the busses are wired or in your implementation of either inw or insw.

On (classic) m68k all of this is not about PCI (Atari Hades PCI is no more), but about ISA and PCMCIA. I.e. no PCI host bridge with a modern understanding of how it should be wired correctly on a big endian platform.

Quoted 8 lines
Quoted 3 lines

Now, on m68k without MMU, inw() doesn't do swapping, but insw() does. This agrees more or less with you and Will, except that the bus seems to be physically swapped?

Yeah that's possible. In the early days people incorrectly thought it would be smart to do that, thus avoiding a byteswap for register accesses .... and causing all data (DMA or FIFO) to be all backward.

Quoted 5 lines

That's for example why the disks in the Tivo are byteswapped 16-bit by 16-bit on the platter (ie, all the data is).

I wouldn't be surprised if some 68k suffered from similar HW designer stupidity.

Yep, Atari IDE suffers from this, too.

Quoted 2 lines

But the "proper" generic rule is byte address invariance, and that implies swap on register access and no swap on byte streams.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#11 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

Quoted 10 lines · Geert Uytterhoeven
Quoted 5 lines

This is due to how the PCI bus is wired to the CPU bus, which is called "byte address invariant". When doing a read of your byte 0, the CPU will effectively read 0 with byte enables picking 48. Since the CPU wants the first byte in the MSB, the bus must be wired up to the CPU such that the MSB is the first byte in address order.

According to
https://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/WritingPCIDrivers/endianness/endianness.html

"Byte-invariant addressing is a property of the bus bridge itself."

Right.

Quoted 8 lines

and

"From the software designer’s perspective, this means that the hardware does not byte swap the data. However, from the hardware designer’s perspective, the hardware must byte swap all data."

So this depends on a correct hardware implementation in the PCI host bridge?

Correct. It is also how AMBA works on BE for example, it's generally accepted that this is the "right" way to wire a bridge.

Quoted 7 lines
Quoted 3 lines

Then something is horribly wrong in those m68k setups :-) Either in the way the busses are wired or in your implementation of either inw or insw.

On (classic) m68k all of this is not about PCI (Atari Hades PCI is no more), but about ISA and PCMCIA. I.e. no PCI host bridge with a modern understanding of how it should be wired correctly on a big endian platform.

There's nothing modern about byte address invariance. The same rule applies to ISA and PCMCIA just the same. It's possible that your specific m68k platforms were designed by monkeys on crack, which seems to be a common breed among HW designers, but that doesn't make it right :-)

Cheers,
Ben.

Acked-by on v1 2/4
#12 lore raw

Re: [RESEND PATCH 2/4] asm-generic: io: don't perform swab during {in,out} string functions

In reply to Will Deacon
Quoted 9 lines · Will Deacon

The {in,out}s{b,w,l} functions are designed to operate on a stream of bytes and therefore should not perform any byte-swapping, regardless of the CPU byte order.

This patch fixes the generic IO header so that {in,out}s{b,w,l} call the __raw_{read,write} functions directly rather than going via the endian-correcting accessors.

Cc Mike Frysinger <[email protected]>
Quoted 64 lines
---
 include/asm-generic/io.h |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
include/asm-generic/io.h +6 -6
index 3607921..403b861 100644
@@ -148,7 +148,7 @@ static inline void insb(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u8 *buf = buffer;
 		do {
-			u8 x = inb(addr);
+			u8 x = __raw_readb(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -161,7 +161,7 @@ static inline void insw(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u16 *buf = buffer;
 		do {
-			u16 x = inw(addr);
+			u16 x = __raw_readw(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -174,7 +174,7 @@ static inline void insl(unsigned long addr, void *buffer, int count)
 	if (count) {
 		u32 *buf = buffer;
 		do {
-			u32 x = inl(addr);
+			u32 x = __raw_readl(addr + PCI_IOBASE);
 			*buf++ = x;
 		} while (--count);
 	}
@@ -187,7 +187,7 @@ static inline void outsb(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u8 *buf = buffer;
 		do {
-			outb(*buf++, addr);
+			__raw_writeb(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
@@ -199,7 +199,7 @@ static inline void outsw(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u16 *buf = buffer;
 		do {
-			outw(*buf++, addr);
+			__raw_writew(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
@@ -211,7 +211,7 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 	if (count) {
 		const u32 *buf = buffer;
 		do {
-			outl(*buf++, addr);
+			__raw_writel(*buf++, addr + PCI_IOBASE);
 		} while (--count);
 	}
 }
#13 lore raw

PATCH RESEND 3/4 mmc: mmci: use io{read,write}*_rep accessors instead of string functions

In reply to Will Deacon

The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface.

This patch replaces the usage of these string functions with io{read,write}{8,16,32}_rep calls instead, which are defined for all architectures.

Cc Arnd Bergmann <[email protected]>
Cc Ben Herrenschmidt <[email protected]>
---
 drivers/mmc/host/mmci.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/mmc/host/mmci.c +4 -4
index edc3e9b..4f125b4 100644
@@ -840,14 +840,14 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
 		if (unlikely(count & 0x3)) {
 			if (count < 4) {
 				unsigned char buf[4];
-				readsl(base + MMCIFIFO, buf, 1);
+				ioread32_rep(base + MMCIFIFO, buf, 1);
 				memcpy(ptr, buf, count);
 			} else {
-				readsl(base + MMCIFIFO, ptr, count >> 2);
+				ioread32_rep(base + MMCIFIFO, ptr, count >> 2);
 				count &= ~0x3;
 			}
 		} else {
-			readsl(base + MMCIFIFO, ptr, count >> 2);
+			ioread32_rep(base + MMCIFIFO, ptr, count >> 2);
 		}
 
 		ptr += count;
@@ -900,7 +900,7 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
 		 * byte become a 32bit write, 7 bytes will be two
 		 * 32bit writes etc.
 		 */
-		writesl(base + MMCIFIFO, ptr, (count + 3) >> 2);
+		iowrite32_rep(base + MMCIFIFO, ptr, (count + 3) >> 2);
 
 		ptr += count;
 		remain -= count;
Signature · 1 line
1.7.4.1
#14 lore raw

PATCH RESEND 4/4 net: smc91x: use io{read,write}*_rep accessors instead of string functions

In reply to Will Deacon

The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface.

This patch replaces the usage of these string functions in the default SMC accessors with io{read,write}{8,16,32}_rep calls instead, which are defined for all architectures.

Cc Arnd Bergmann <[email protected]>
Cc Ben Herrenschmidt <[email protected]>
---
 drivers/net/ethernet/smsc/smc91x.h |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)
drivers/net/ethernet/smsc/smc91x.h +10 -10
index 5f53fbb..370e13d 100644
@@ -286,16 +286,16 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
 
 #define SMC_IO_SHIFT		(lp->io_shift)
 
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+#define SMC_inb(a, r)		ioread8((a) + (r))
+#define SMC_inw(a, r)		ioread16((a) + (r))
+#define SMC_inl(a, r)		ioread32((a) + (r))
+#define SMC_outb(v, a, r)	iowrite8(v, (a) + (r))
+#define SMC_outw(v, a, r)	iowrite16(v, (a) + (r))
+#define SMC_outl(v, a, r)	iowrite32(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	ioread16_rep((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	iowrite16_rep((a) + (r), p, l)
+#define SMC_insl(a, r, p, l)	ioread32_rep((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	iowrite32_rep((a) + (r), p, l)
 
 #define RPC_LSA_DEFAULT		RPC_LED_100_10
 #define RPC_LSB_DEFAULT		RPC_LED_TX_RX
Signature · 1 line
1.7.4.1
#15 lore raw

Re: [RESEND PATCH 4/4] net: smc91x: use io{read,write}*_rep accessors instead of string functions

Quoted 6 lines · Will Deacon

The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface.

This patch replaces the usage of these string functions in the default SMC accessors with io{read,write}{8,16,32}_rep calls instead, which are defined for all architectures.

Hi,

Should this patch (and the mmc one) precede patch 1?

Also there appear to be some other places that it's used (e.g. smsc911x.c and smc911x.h). I guess these should be fixed up first too?

Cheers
James

#16 lore raw

Re: [RESEND PATCH 4/4] net: smc91x: use io{read,write}*_rep accessors instead of string functions

Quoted 11 lines · James Hogan
Quoted 6 lines · Will Deacon

The {read,write}s{b,w,l} operations are not defined by all architectures and are being removed from the asm-generic/io.h interface.

This patch replaces the usage of these string functions in the default SMC accessors with io{read,write}{8,16,32}_rep calls instead, which are defined for all architectures.

Hi,

Should this patch (and the mmc one) precede patch 1?

Yup, I can reorder that easily enough.

Quoted 2 lines

Also there appear to be some other places that it's used (e.g. smsc911x.c and smc911x.h). I guess these should be fixed up first too?

I could have a look if you like, but I'm wary of changing the I/O accessors in anything but a mechanical fashion given that I can't test any of my changes.

Will