* [PATCH] sparc: Remove IO memcpy and memset from sparc code
@ 2026-10-29 14:53 Julian Vetter
2026-10-29 15:13 ` Arnd Bergmann
0 siblings, 1 reply; 4+ messages in thread
From: Julian Vetter @ 2026-10-29 14:53 UTC (permalink / raw)
To: David S . Miller, Andreas Larsson
Cc: Arnd Bergmann, sparclinux, linux-kernel, Julian Vetter
Remove the IO memcpy and memset from sparc specific code and fall back
to the implementations from lib/iomem_copy.c. They use word accesses if
the buffers are aligned and only fall back to byte accesses for
potentially unaligned parts of a buffer, while the sparc versions always
use byte-wise readb()/writeb() accesses. Other architectures, such as
arm64, csky, loongarch and parisc, have already been converted to the
generic implementation.
This does not drop any memory barriers. The sparc versions don't use
mb(), and the rmb()/wmb() implied by readb()/writeb() on sparc32 and
sparc64 are only compiler barriers.
Signed-off-by: Julian Vetter <julian@outer-limits.org>
---
arch/sparc/include/asm/io_32.h | 40 ----------------------------------
arch/sparc/include/asm/io_64.h | 38 --------------------------------
2 files changed, 78 deletions(-)
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index 549f0a72280d..5df651ee5935 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -7,10 +7,6 @@
#define IO_SPACE_LIMIT 0xffffffff
-#define memset_io(d,c,sz) _memset_io(d,c,sz)
-#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
-#define memcpy_toio(d,s,sz) _memcpy_toio(d,s,sz)
-
/*
* Bus number may be embedded in the higher bits of the physical address.
* This is why we have no bus number argument to ioremap().
@@ -20,42 +16,6 @@ void iounmap(volatile void __iomem *addr);
#include <asm-generic/io.h>
-static inline void _memset_io(volatile void __iomem *dst,
- int c, __kernel_size_t n)
-{
- volatile void __iomem *d = dst;
-
- while (n--) {
- writeb(c, d);
- d++;
- }
-}
-
-static inline void _memcpy_fromio(void *dst, const volatile void __iomem *src,
- __kernel_size_t n)
-{
- char *d = dst;
-
- while (n--) {
- char tmp = readb(src);
- *d++ = tmp;
- src++;
- }
-}
-
-static inline void _memcpy_toio(volatile void __iomem *dst, const void *src,
- __kernel_size_t n)
-{
- const char *s = src;
- volatile void __iomem *d = dst;
-
- while (n--) {
- char tmp = *s++;
- writeb(tmp, d);
- d++;
- }
-}
-
/*
* SBus accessors.
*
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h
index d8ed296624af..83fb1cf90601 100644
--- a/arch/sparc/include/asm/io_64.h
+++ b/arch/sparc/include/asm/io_64.h
@@ -349,17 +349,6 @@ static inline void sbus_memset_io(volatile void __iomem *dst, int c, __kernel_si
}
}
-static inline void memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
-{
- volatile void __iomem *d = dst;
-
- while (n--) {
- writeb(c, d);
- d++;
- }
-}
-#define memset_io memset_io
-
static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
__kernel_size_t n)
{
@@ -373,19 +362,6 @@ static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *sr
}
-static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
- __kernel_size_t n)
-{
- char *d = dst;
-
- while (n--) {
- char tmp = readb(src);
- *d++ = tmp;
- src++;
- }
-}
-#define memcpy_fromio memcpy_fromio
-
static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
__kernel_size_t n)
{
@@ -399,20 +375,6 @@ static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
}
}
-static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
- __kernel_size_t n)
-{
- const char *s = src;
- volatile void __iomem *d = dst;
-
- while (n--) {
- char tmp = *s++;
- writeb(tmp, d);
- d++;
- }
-}
-#define memcpy_toio memcpy_toio
-
#ifdef __KERNEL__
/* On sparc64 we have the whole physical IO address space accessible
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sparc: Remove IO memcpy and memset from sparc code
2026-10-29 14:53 [PATCH] sparc: Remove IO memcpy and memset from sparc code Julian Vetter
@ 2026-10-29 15:13 ` Arnd Bergmann
2026-10-30 9:03 ` Julian Vetter
0 siblings, 1 reply; 4+ messages in thread
From: Arnd Bergmann @ 2026-10-29 15:13 UTC (permalink / raw)
To: Julian Vetter, David S . Miller, Andreas Larsson; +Cc: sparclinux, linux-kernel
On Thu, Oct 29, 2026, at 15:53, Julian Vetter wrote:
> Remove the IO memcpy and memset from sparc specific code and fall back
> to the implementations from lib/iomem_copy.c. They use word accesses if
> the buffers are aligned and only fall back to byte accesses for
> potentially unaligned parts of a buffer, while the sparc versions always
> use byte-wise readb()/writeb() accesses. Other architectures, such as
> arm64, csky, loongarch and parisc, have already been converted to the
> generic implementation.
>
> This does not drop any memory barriers. The sparc versions don't use
> mb(), and the rmb()/wmb() implied by readb()/writeb() on sparc32 and
> sparc64 are only compiler barriers.
Hi Julian,
I suspect the sparc64 patch is wrong because the generic
code relies on __raw_readq()/__raw_readl() to produce
native-endian data, while the sparc64 version looks like
they work on little-endian data the same way as readq()/readl().
Do you know if the PCI host bridge on sparc64 does an implicit
byte swap for memory space? If it does, the __raw_ accessors
have to flip swap the data another time for this to work.
Arnd
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sparc: Remove IO memcpy and memset from sparc code
2026-10-29 15:13 ` Arnd Bergmann
@ 2026-10-30 9:03 ` Julian Vetter
2026-10-30 9:26 ` Arnd Bergmann
0 siblings, 1 reply; 4+ messages in thread
From: Julian Vetter @ 2026-10-30 9:03 UTC (permalink / raw)
To: Arnd Bergmann, David S . Miller, Andreas Larsson; +Cc: sparclinux, linux-kernel
On 10/29/26 16:13, Arnd Bergmann wrote:
> On Thu, Oct 29, 2026, at 15:53, Julian Vetter wrote:
>> Remove the IO memcpy and memset from sparc specific code and fall back
>> to the implementations from lib/iomem_copy.c. They use word accesses if
>> the buffers are aligned and only fall back to byte accesses for
>> potentially unaligned parts of a buffer, while the sparc versions always
>> use byte-wise readb()/writeb() accesses. Other architectures, such as
>> arm64, csky, loongarch and parisc, have already been converted to the
>> generic implementation.
>>
>> This does not drop any memory barriers. The sparc versions don't use
>> mb(), and the rmb()/wmb() implied by readb()/writeb() on sparc32 and
>> sparc64 are only compiler barriers.
>
> Hi Julian,
>
> I suspect the sparc64 patch is wrong because the generic
> code relies on __raw_readq()/__raw_readl() to produce
> native-endian data, while the sparc64 version looks like
> they work on little-endian data the same way as readq()/readl().
>
> Do you know if the PCI host bridge on sparc64 does an implicit
> byte swap for memory space? If it does, the __raw_ accessors
> have to flip swap the data another time for this to work.
>
> Arnd
Hello Arnd,
thank you for your reply! I'm not sure, but to me it seems unlikely that
the PCI host bridge swaps. On sparc64 readl()/readq() use the flag
ASI_PHYS_BYPASS_EC_E_L, so they work on little-endian data. The CPU does
the byte swap here. The __raw_*() accessors use ASI_PHYS_BYPASS_EC_E,
which does not swap (which are used in lib/io_memcpy.c as well), so they
return the data in address order. If the PCI host bridge also swapped,
readl() would return double-swapped values, no?
And other I/O functions, e.g., readsl()/writesl() and
ioread32_rep()/iowrite32_rep() end up in insl()/outsl() in
arch/sparc/lib/PeeCeeI.c, which copy buffers with
__raw_readl()/__raw_writel(). And __ioread32_copy()/__iowrite32_copy()
in lib/iomap_copy.c use the __raw_ accessors on sparc64 as well.
But that's just from me looking at the code and compiling the
sparc32_defconfig and sparc64_defconfig. I have no sparc platform, so
can't test it. Maybe some sparc expert can comment.
Julian
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sparc: Remove IO memcpy and memset from sparc code
2026-10-30 9:03 ` Julian Vetter
@ 2026-10-30 9:26 ` Arnd Bergmann
0 siblings, 0 replies; 4+ messages in thread
From: Arnd Bergmann @ 2026-10-30 9:26 UTC (permalink / raw)
To: Julian Vetter, David S . Miller, Andreas Larsson; +Cc: sparclinux, linux-kernel
On Fri, Oct 30, 2026, at 10:03, Julian Vetter wrote:
> On 10/29/26 16:13, Arnd Bergmann wrote:
>
> thank you for your reply! I'm not sure, but to me it seems unlikely that
> the PCI host bridge swaps. On sparc64 readl()/readq() use the flag
> ASI_PHYS_BYPASS_EC_E_L, so they work on little-endian data. The CPU does
> the byte swap here. The __raw_*() accessors use ASI_PHYS_BYPASS_EC_E,
> which does not swap (which are used in lib/io_memcpy.c as well), so they
> return the data in address order.
Ok, good. I missed the '_L' bit and assumed they were the same.
In this case your patch looks good.
> And other I/O functions, e.g., readsl()/writesl() and
> ioread32_rep()/iowrite32_rep() end up in insl()/outsl() in
> arch/sparc/lib/PeeCeeI.c, which copy buffers with
> __raw_readl()/__raw_writel(). And __ioread32_copy()/__iowrite32_copy()
> in lib/iomap_copy.c use the __raw_ accessors on sparc64 as well.
>
> But that's just from me looking at the code and compiling the
> sparc32_defconfig and sparc64_defconfig. I have no sparc platform, so
> can't test it. Maybe some sparc expert can comment.
I'm sure it's fine then. For your patch:
Reviewed-by: Arnd Bergman <arnd@arndb.de>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-30 9:26 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 14:53 [PATCH] sparc: Remove IO memcpy and memset from sparc code Julian Vetter
2026-10-29 15:13 ` Arnd Bergmann
2026-10-30 9:03 ` Julian Vetter
2026-10-30 9:26 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®