aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/include/asm/atomic.h
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2018-12-20 17:18:12 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2019-05-07 10:36:31 -0700
commitf7c34874f04a80d6c39a32f08da2529e59602d3c (patch)
treea225ab153205701d24bee7423fc950a9009cb533 /arch/xtensa/include/asm/atomic.h
parentxtensa: clean up inline assembly in futex.h (diff)
downloadlinux-dev-f7c34874f04a80d6c39a32f08da2529e59602d3c.tar.xz
linux-dev-f7c34874f04a80d6c39a32f08da2529e59602d3c.zip
xtensa: add exclusive atomics support
Implement atomic primitives using exclusive access opcodes available in the recent xtensa cores. Since l32ex/s32ex don't have any memory ordering guarantees don't define __smp_mb__before_atomic/__smp_mb__after_atomic to make them use memw. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch/xtensa/include/asm/atomic.h')
-rw-r--r--arch/xtensa/include/asm/atomic.h62
1 files changed, 61 insertions, 1 deletions
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index 4e7311f58ae8..7b00d26f472e 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -56,7 +56,67 @@
*/
#define atomic_set(v,i) WRITE_ONCE((v)->counter, (i))
-#if XCHAL_HAVE_S32C1I
+#if XCHAL_HAVE_EXCLUSIVE
+#define ATOMIC_OP(op) \
+static inline void atomic_##op(int i, atomic_t *v) \
+{ \
+ unsigned long tmp; \
+ int result; \
+ \
+ __asm__ __volatile__( \
+ "1: l32ex %1, %3\n" \
+ " " #op " %0, %1, %2\n" \
+ " s32ex %0, %3\n" \
+ " getex %0\n" \
+ " beqz %0, 1b\n" \
+ : "=&a" (result), "=&a" (tmp) \
+ : "a" (i), "a" (v) \
+ : "memory" \
+ ); \
+} \
+
+#define ATOMIC_OP_RETURN(op) \
+static inline int atomic_##op##_return(int i, atomic_t *v) \
+{ \
+ unsigned long tmp; \
+ int result; \
+ \
+ __asm__ __volatile__( \
+ "1: l32ex %1, %3\n" \
+ " " #op " %0, %1, %2\n" \
+ " s32ex %0, %3\n" \
+ " getex %0\n" \
+ " beqz %0, 1b\n" \
+ " " #op " %0, %1, %2\n" \
+ : "=&a" (result), "=&a" (tmp) \
+ : "a" (i), "a" (v) \
+ : "memory" \
+ ); \
+ \
+ return result; \
+}
+
+#define ATOMIC_FETCH_OP(op) \
+static inline int atomic_fetch_##op(int i, atomic_t *v) \
+{ \
+ unsigned long tmp; \
+ int result; \
+ \
+ __asm__ __volatile__( \
+ "1: l32ex %1, %3\n" \
+ " " #op " %0, %1, %2\n" \
+ " s32ex %0, %3\n" \
+ " getex %0\n" \
+ " beqz %0, 1b\n" \
+ : "=&a" (result), "=&a" (tmp) \
+ : "a" (i), "a" (v) \
+ : "memory" \
+ ); \
+ \
+ return tmp; \
+}
+
+#elif XCHAL_HAVE_S32C1I
#define ATOMIC_OP(op) \
static inline void atomic_##op(int i, atomic_t * v) \
{ \