Messages in this thread Patch in this message | | | From | Brian Gerst <> | Subject | [PATCH] x86: Split off mem*io functions | Date | Sun, 11 Dec 2011 17:10:36 -0500 |
| |
Commit 6175ddf06b6172046a329e3abfd9c901a43efd2e changed the mem*io functions to use the standard memcpy/memset routines, but there were unintended consequences. Some devices cannot cope with 64-bit or non-sequential accesses that the optimized routines do. Change them back to simple 32-bit sequential writes.
Signed-off-by: Brian Gerst <brgerst@gmail.com> --- arch/x86/include/asm/io.h | 20 +++----------------- arch/x86/lib/Makefile | 1 + arch/x86/lib/io.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 arch/x86/lib/io.c
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index d8e8eef..8115978 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -199,23 +199,9 @@ extern void set_iounmap_nonlazy(void); */ #define xlate_dev_kmem_ptr(p) p -static inline void -memset_io(volatile void __iomem *addr, unsigned char val, size_t count) -{ - memset((void __force *)addr, val, count); -} - -static inline void -memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count) -{ - memcpy(dst, (const void __force *)src, count); -} - -static inline void -memcpy_toio(volatile void __iomem *dst, const void *src, size_t count) -{ - memcpy((void __force *)dst, src, count); -} +extern void memset_io(volatile void __iomem *addr, unsigned char val, size_t count); +extern void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count); +extern void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count); /* * ISA space is 'always mapped' on a typical x86 system, no need to diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b00f678..160d934 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -17,6 +17,7 @@ clean-files := inat-tables.c obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o lib-y := delay.o +lib-y += io.o lib-y += thunk_$(BITS).o lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o lib-y += memcpy_$(BITS).o diff --git a/arch/x86/lib/io.c b/arch/x86/lib/io.c new file mode 100644 index 0000000..7acdd6d --- /dev/null +++ b/arch/x86/lib/io.c @@ -0,0 +1,41 @@ +#include <asm/io.h> +#include <asm/types.h> +#include <linux/module.h> + +/* + * Some devices can't handle 64-bit or non-sequential accesses. + * Use simple string instructions here instead of the normal optimized + * memcpy/menset functions. + */ + +void memset_io(volatile void __iomem *addr, unsigned char val, size_t count) +{ + unsigned int v = val * 0x01010101; + size_t c = count / 4; + asm volatile("rep; stosl" : "+D" (addr), "+c" (c) : "a" (v) : "memory"); + c = count & 3; + if (c) + asm volatile("rep; stosb" : "+D" (addr), "+c" (c) : "a" (v) : "memory"); +} +EXPORT_SYMBOL(memset_io); + +static void __memcpy_io(void *dst, const void *src, size_t count) +{ + size_t c = count / 4; + asm volatile("rep; movsl" : "+S" (src), "+D" (dst), "+c" (c) : : "memory"); + c = count & 3; + if (c) + asm volatile("rep; movsb" : "+S" (src), "+D" (dst), "+c" (c) : : "memory"); +} + +void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count) +{ + __memcpy_io(dst, (const void __force *)src, count); +} +EXPORT_SYMBOL(memcpy_fromio); + +void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count) +{ + __memcpy_io((void __force *)dst, src, count); +} +EXPORT_SYMBOL(memcpy_toio); -- 1.7.4.4
| |