commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=24d7e998afa1cb6f4af1306580880c8e8358742b
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

In blackfin SMP architecture, no cache coherence among cores is supppored by hardware. Data protected
by spin lock or atomic operation are kept consistent by invalidating entired local cache in spin lock APIs
and smp memory barrier APIs on the other cores.

Non atomic operations in current Blackfin SMP kernel run smp memory barrier. This patch add smp memory
barrier to some atomic operations that are defined in Documents/memory-barriers.txt .

Signed-off-by: Sonic Zhang <[email protected]>
---
 arch/blackfin/include/asm/atomic.h |   21 +++++++++++++++++++--
 arch/blackfin/include/asm/bitops.h |   13 ++++++++++---
 arch/blackfin/include/asm/system.h |    2 ++
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index 54c6e28..08f1e2a 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -9,6 +9,7 @@
 
 #ifdef CONFIG_SMP
 
+#include <asm/system.h>
 #include <linux/linkage.h>
 
 asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
@@ -20,8 +21,24 @@ asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
 
 #define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
 
-#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
-#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
+static inline int __atomic_add_return(int i, atomic_t *v)
+{
+	int ret;
+	ret = __raw_atomic_update_asm(&(v)->counter, i);
+	smp_mb();
+	return ret;
+}
+
+static inline int __atomic_sub_return(int i, atomic_t *v)
+{
+	int ret;
+	ret = __raw_atomic_update_asm(&(v)->counter, -(i));
+	smp_mb();
+	return ret;
+}
+
+#define atomic_add_return(i, v) __atomic_add_return(i, v)
+#define atomic_sub_return(i, v) __atomic_sub_return(i, v)
 
 #define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
 #define atomic_set_mask(m, v)   __raw_atomic_set_asm(&(v)->counter, m)
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
index 8a0fed1..8dd3e6d 100644
--- a/arch/blackfin/include/asm/bitops.h
+++ b/arch/blackfin/include/asm/bitops.h
@@ -42,6 +42,7 @@
 #else
 
 #include <asm/byteorder.h>	/* swab32 */
+#include <asm/system.h>
 #include <linux/linkage.h>
 
 asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr);
@@ -85,19 +86,25 @@ static inline int test_bit(int nr, const volatile unsigned long *addr)
 static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
 {
 	volatile unsigned long *a = addr + (nr >> 5);
-	return __raw_bit_test_set_asm(a, nr & 0x1f);
+	int ret = __raw_bit_test_set_asm(a, nr & 0x1f);
+	smp_mb();
+	return ret;
 }
 
 static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
 {
 	volatile unsigned long *a = addr + (nr >> 5);
-	return __raw_bit_test_clear_asm(a, nr & 0x1f);
+	int ret = __raw_bit_test_clear_asm(a, nr & 0x1f);
+	smp_mb();
+	return ret;
 }
 
 static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 {
 	volatile unsigned long *a = addr + (nr >> 5);
-	return __raw_bit_test_toggle_asm(a, nr & 0x1f);
+	int ret = __raw_bit_test_toggle_asm(a, nr & 0x1f);
+	smp_mb();
+	return ret;
 }
 
 /*
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
index 44bd0cc..c0ce310 100644
--- a/arch/blackfin/include/asm/system.h
+++ b/arch/blackfin/include/asm/system.h
@@ -91,6 +91,8 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 		break;
 	}
 
+	smp_mb();
+
 	return tmp;
 }
 #define cmpxchg(ptr, o, n) \
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to