Skip to content

Commit 8318f7c

Browse files
committed
csky: optimize memcpy_{from,to}io() and memset_io()
Optimize memcpy_{from,to}io() and memset_io() by transferring in 64 bit as much as possible with minimized barrier usage. This simplest optimization brings faster throughput compare to current byte-by-byte read and write with barrier in the loop. Code's skeleton is taken from the powerpc & arm64. Signed-off-by: Guo Ren <[email protected]> Signed-off-by: Guo Ren <[email protected]>
1 parent e4df2d5 commit 8318f7c

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

arch/csky/include/asm/io.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@
3131
#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); })
3232
#endif
3333

34+
/*
35+
* String version of I/O memory access operations.
36+
*/
37+
extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
38+
extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
39+
extern void __memset_io(volatile void __iomem *, int, size_t);
40+
41+
#define memset_io(c,v,l) __memset_io((c),(v),(l))
42+
#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l))
43+
#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l))
44+
3445
/*
3546
* I/O memory mapping functions.
3647
*/

arch/csky/kernel/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
extra-y := head.o vmlinux.lds
33

44
obj-y += entry.o atomic.o signal.o traps.o irq.o time.o vdso.o vdso/
5-
obj-y += power.o syscall.o syscall_table.o setup.o
5+
obj-y += power.o syscall.o syscall_table.o setup.o io.o
66
obj-y += process.o cpu-probe.o ptrace.o stacktrace.o
77
obj-y += probes/
88

arch/csky/kernel/io.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/export.h>
4+
#include <linux/types.h>
5+
#include <linux/io.h>
6+
7+
/*
8+
* Copy data from IO memory space to "real" memory space.
9+
*/
10+
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
11+
{
12+
while (count && !IS_ALIGNED((unsigned long)from, 4)) {
13+
*(u8 *)to = __raw_readb(from);
14+
from++;
15+
to++;
16+
count--;
17+
}
18+
19+
while (count >= 4) {
20+
*(u32 *)to = __raw_readl(from);
21+
from += 4;
22+
to += 4;
23+
count -= 4;
24+
}
25+
26+
while (count) {
27+
*(u8 *)to = __raw_readb(from);
28+
from++;
29+
to++;
30+
count--;
31+
}
32+
}
33+
EXPORT_SYMBOL(__memcpy_fromio);
34+
35+
/*
36+
* Copy data from "real" memory space to IO memory space.
37+
*/
38+
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
39+
{
40+
while (count && !IS_ALIGNED((unsigned long)to, 4)) {
41+
__raw_writeb(*(u8 *)from, to);
42+
from++;
43+
to++;
44+
count--;
45+
}
46+
47+
while (count >= 4) {
48+
__raw_writel(*(u32 *)from, to);
49+
from += 4;
50+
to += 4;
51+
count -= 4;
52+
}
53+
54+
while (count) {
55+
__raw_writeb(*(u8 *)from, to);
56+
from++;
57+
to++;
58+
count--;
59+
}
60+
}
61+
EXPORT_SYMBOL(__memcpy_toio);
62+
63+
/*
64+
* "memset" on IO memory space.
65+
*/
66+
void __memset_io(volatile void __iomem *dst, int c, size_t count)
67+
{
68+
u32 qc = (u8)c;
69+
70+
qc |= qc << 8;
71+
qc |= qc << 16;
72+
73+
while (count && !IS_ALIGNED((unsigned long)dst, 4)) {
74+
__raw_writeb(c, dst);
75+
dst++;
76+
count--;
77+
}
78+
79+
while (count >= 4) {
80+
__raw_writel(qc, dst);
81+
dst += 4;
82+
count -= 4;
83+
}
84+
85+
while (count) {
86+
__raw_writeb(c, dst);
87+
dst++;
88+
count--;
89+
}
90+
}
91+
EXPORT_SYMBOL(__memset_io);

0 commit comments

Comments
 (0)