aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lib
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-31 13:37:12 +1100
committerPaul Mackerras <paulus@samba.org>2005-10-31 13:37:12 +1100
commit23fd07750a789a66fe88cf173d52a18f1a387da4 (patch)
tree06fdd6df35fdb835abdaa9b754d62f6b84b97250 /arch/mips/lib
parentppc: remove duplicate export of cur_cpu_spec (diff)
parentMerge master.kernel.org:/home/rmk/linux-2.6-serial (diff)
downloadlinux-dev-23fd07750a789a66fe88cf173d52a18f1a387da4.tar.xz
linux-dev-23fd07750a789a66fe88cf173d52a18f1a387da4.zip
Merge ../linux-2.6 by hand
Diffstat (limited to 'arch/mips/lib')
-rw-r--r--arch/mips/lib/Makefile4
-rw-r--r--arch/mips/lib/csum_partial_copy.c8
-rw-r--r--arch/mips/lib/memcpy.S15
-rw-r--r--arch/mips/lib/uncached.c76
4 files changed, 97 insertions, 6 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 037303412909..cf12caf80774 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,8 +2,8 @@
# Makefile for MIPS-specific library files..
#
-lib-y += csum_partial_copy.o memcpy.o promlib.o \
- strlen_user.o strncpy_user.o strnlen_user.o
+lib-y += csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \
+ strnlen_user.o uncached.o
obj-y += iomap.o
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
index ffed0a6a1c16..6e9f366f961d 100644
--- a/arch/mips/lib/csum_partial_copy.c
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -16,8 +16,8 @@
/*
* copy while checksumming, otherwise like csum_partial
*/
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum)
+unsigned int csum_partial_copy_nocheck(const unsigned char *src,
+ unsigned char *dst, int len, unsigned int sum)
{
/*
* It's 2:30 am and I don't feel like doing it real ...
@@ -33,8 +33,8 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum, int *err_ptr)
+unsigned int csum_partial_copy_from_user (const unsigned char __user *src,
+ unsigned char *dst, int len, unsigned int sum, int *err_ptr)
{
int missing;
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index a78865f76547..7f9aafa4d80e 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -13,6 +13,21 @@
* Mnemonic names for arguments to memcpy/__copy_user
*/
#include <linux/config.h>
+
+/*
+ * Hack to resolve longstanding prefetch issue
+ *
+ * Prefetching may be fatal on some systems if we're prefetching beyond the
+ * end of memory on some systems. It's also a seriously bad idea on non
+ * dma-coherent systems.
+ */
+#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27)
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+#ifdef CONFIG_MIPS_MALTA
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/regdef.h>
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
new file mode 100644
index 000000000000..98ce89f8068b
--- /dev/null
+++ b/arch/mips/lib/uncached.c
@@ -0,0 +1,76 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Thiemo Seufer
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ * Author: Maciej W. Rozycki <macro@mips.com>
+ */
+
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/bug.h>
+
+#ifndef CKSEG2
+#define CKSEG2 CKSSEG
+#endif
+#ifndef TO_PHYS_MASK
+#define TO_PHYS_MASK -1
+#endif
+
+/*
+ * FUNC is executed in one of the uncached segments, depending on its
+ * original address as follows:
+ *
+ * 1. If the original address is in CKSEG0 or CKSEG1, then the uncached
+ * segment used is CKSEG1.
+ * 2. If the original address is in XKPHYS, then the uncached segment
+ * used is XKPHYS(2).
+ * 3. Otherwise it's a bug.
+ *
+ * The same remapping is done with the stack pointer. Stack handling
+ * works because we don't handle stack arguments or more complex return
+ * values, so we can avoid sharing the same stack area between a cached
+ * and the uncached mode.
+ */
+unsigned long __init run_uncached(void *func)
+{
+ register long sp __asm__("$sp");
+ register long ret __asm__("$2");
+ long lfunc = (long)func, ufunc;
+ long usp;
+
+ if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
+ usp = CKSEG1ADDR(sp);
+ else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
+ (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0))
+ usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
+ XKPHYS_TO_PHYS((long long)sp));
+ else {
+ BUG();
+ usp = sp;
+ }
+ if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2)
+ ufunc = CKSEG1ADDR(lfunc);
+ else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
+ (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0))
+ ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
+ XKPHYS_TO_PHYS((long long)lfunc));
+ else {
+ BUG();
+ ufunc = lfunc;
+ }
+
+ __asm__ __volatile__ (
+ " move $16, $sp\n"
+ " move $sp, %1\n"
+ " jalr %2\n"
+ " move $sp, $16"
+ : "=r" (ret)
+ : "r" (usp), "r" (ufunc)
+ : "$16", "$31");
+
+ return ret;
+}