[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1323641436-12249-1-git-send-email-brgerst@gmail.com>
Date: Sun, 11 Dec 2011 17:10:36 -0500
From: Brian Gerst <brgerst@...il.com>
To: x86@...nel.org
Cc: linux-kernel@...r.kernel.org, tim@...ngt.org, hpa@...or.com,
torvalds@...ux-foundation.org
Subject: [PATCH] x86: Split off mem*io functions
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@...il.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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists