summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/asm-arm/bitops.h4
-rw-r--r--include/asm-arm/locks.h36
-rw-r--r--include/asm-arm/spinlock.h53
-rw-r--r--include/asm-arm/system.h5
4 files changed, 69 insertions, 29 deletions
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 4edd4dc40c5b..c1adc6b3e86d 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -21,8 +21,8 @@
 
 #include <asm/system.h>
 
-#define smp_mb__before_clear_bit()	do { } while (0)
-#define smp_mb__after_clear_bit()	do { } while (0)
+#define smp_mb__before_clear_bit()	mb()
+#define smp_mb__after_clear_bit()	mb()
 
 /*
  * These functions are the basis of our bit ops.
diff --git a/include/asm-arm/locks.h b/include/asm-arm/locks.h
index 9cb33fcc06c1..f08dc8447913 100644
--- a/include/asm-arm/locks.h
+++ b/include/asm-arm/locks.h
@@ -28,7 +28,8 @@
 "	blmi	" #fail				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	})
 
 #define __down_op_ret(ptr,fail)			\
@@ -48,12 +49,14 @@
 "	mov	%0, ip"				\
 	: "=&r" (ret)				\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	ret;					\
 	})
 
 #define __up_op(ptr,wake)			\
 	({					\
+	smp_mb();				\
 	__asm__ __volatile__(			\
 	"@ up_op\n"				\
 "1:	ldrex	lr, [%0]\n"			\
@@ -66,7 +69,7 @@
 "	blle	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
 	})
 
 /*
@@ -92,11 +95,13 @@
 "	blne	" #fail				\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	})
 
 #define __up_op_write(ptr,wake)			\
 	({					\
+	smp_mb();				\
 	__asm__ __volatile__(			\
 	"@ up_op_read\n"			\
 "1:	ldrex	lr, [%0]\n"			\
@@ -108,7 +113,7 @@
 "	blcs	" #wake				\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
 	})
 
 #define __down_op_read(ptr,fail)		\
@@ -116,6 +121,7 @@
 
 #define __up_op_read(ptr,wake)			\
 	({					\
+	smp_mb();				\
 	__asm__ __volatile__(			\
 	"@ up_op_read\n"			\
 "1:	ldrex	lr, [%0]\n"			\
@@ -128,7 +134,7 @@
 "	bleq	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
 	})
 
 #else
@@ -148,7 +154,8 @@
 "	blmi	" #fail				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	})
 
 #define __down_op_ret(ptr,fail)			\
@@ -169,12 +176,14 @@
 "	mov	%0, ip"				\
 	: "=&r" (ret)				\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	ret;					\
 	})
 
 #define __up_op(ptr,wake)			\
 	({					\
+	smp_mb();				\
 	__asm__ __volatile__(			\
 	"@ up_op\n"				\
 "	mrs	ip, cpsr\n"			\
@@ -188,7 +197,7 @@
 "	blle	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
 	})
 
 /*
@@ -215,7 +224,8 @@
 "	blne	" #fail				\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	})
 
 #define __up_op_write(ptr,wake)			\
@@ -233,7 +243,8 @@
 "	blcs	" #wake				\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
+	smp_mb();				\
 	})
 
 #define __down_op_read(ptr,fail)		\
@@ -241,6 +252,7 @@
 
 #define __up_op_read(ptr,wake)			\
 	({					\
+	smp_mb();				\
 	__asm__ __volatile__(			\
 	"@ up_op_read\n"			\
 "	mrs	ip, cpsr\n"			\
@@ -254,7 +266,7 @@
 "	bleq	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc", "memory");		\
+	: "ip", "lr", "cc");			\
 	})
 
 #endif
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 9705d5eec94c..1f906d09b688 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -8,9 +8,10 @@
 /*
  * ARMv6 Spin-locking.
  *
- * We (exclusively) read the old value, and decrement it.  If it
- * hits zero, we may have won the lock, so we try (exclusively)
- * storing it.
+ * We exclusively read the old value.  If it is zero, we may have
+ * won the lock, so we try exclusively storing it.  A memory barrier
+ * is required after we get a lock, and before we release it, because
+ * V6 CPUs are assumed to have weakly ordered memory.
  *
  * Unlocked value: 0
  * Locked value: 1
@@ -41,7 +42,9 @@ static inline void _raw_spin_lock(spinlock_t *lock)
 "	bne	1b"
 	: "=&r" (tmp)
 	: "r" (&lock->lock), "r" (1)
-	: "cc", "memory");
+	: "cc");
+
+	smp_mb();
 }
 
 static inline int _raw_spin_trylock(spinlock_t *lock)
@@ -54,18 +57,25 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
 "	strexeq	%0, %2, [%1]"
 	: "=&r" (tmp)
 	: "r" (&lock->lock), "r" (1)
-	: "cc", "memory");
-
-	return tmp == 0;
+	: "cc");
+
+	if (tmp == 0) {
+		smp_mb();
+		return 1;
+	} else {
+		return 0;
+	}
 }
 
 static inline void _raw_spin_unlock(spinlock_t *lock)
 {
+	smp_mb();
+
 	__asm__ __volatile__(
 "	str	%1, [%0]"
 	:
 	: "r" (&lock->lock), "r" (0)
-	: "cc", "memory");
+	: "cc");
 }
 
 /*
@@ -98,7 +108,9 @@ static inline void _raw_write_lock(rwlock_t *rw)
 "	bne	1b"
 	: "=&r" (tmp)
 	: "r" (&rw->lock), "r" (0x80000000)
-	: "cc", "memory");
+	: "cc");
+
+	smp_mb();
 }
 
 static inline int _raw_write_trylock(rwlock_t *rw)
@@ -111,18 +123,25 @@ static inline int _raw_write_trylock(rwlock_t *rw)
 "	strexeq	%0, %2, [%1]"
 	: "=&r" (tmp)
 	: "r" (&rw->lock), "r" (0x80000000)
-	: "cc", "memory");
-
-	return tmp == 0;
+	: "cc");
+
+	if (tmp == 0) {
+		smp_mb();
+		return 1;
+	} else {
+		return 0;
+	}
 }
 
 static inline void _raw_write_unlock(rwlock_t *rw)
 {
+	smp_mb();
+
 	__asm__ __volatile__(
 	"str	%1, [%0]"
 	:
 	: "r" (&rw->lock), "r" (0)
-	: "cc", "memory");
+	: "cc");
 }
 
 /*
@@ -149,13 +168,17 @@ static inline void _raw_read_lock(rwlock_t *rw)
 "	bmi	1b"
 	: "=&r" (tmp), "=&r" (tmp2)
 	: "r" (&rw->lock)
-	: "cc", "memory");
+	: "cc");
+
+	smp_mb();
 }
 
 static inline void _raw_read_unlock(rwlock_t *rw)
 {
 	unsigned long tmp, tmp2;
 
+	smp_mb();
+
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%2]\n"
 "	sub	%0, %0, #1\n"
@@ -164,7 +187,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
 "	bne	1b"
 	: "=&r" (tmp), "=&r" (tmp2)
 	: "r" (&rw->lock)
-	: "cc", "memory");
+	: "cc");
 }
 
 #define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 3f9c3626a73c..8efa4ebdcacb 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -139,7 +139,12 @@ extern unsigned int user_debug;
 #define vectors_high()	(0)
 #endif
 
+#if __LINUX_ARM_ARCH__ >= 6
+#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory")
+#else
 #define mb() __asm__ __volatile__ ("" : : : "memory")
+#endif
 #define rmb() mb()
 #define wmb() mb()
 #define read_barrier_depends() do { } while(0)