]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/tile/include/asm/cmpxchg.h
tile: rework <asm/cmpxchg.h>
[karo-tx-linux.git] / arch / tile / include / asm / cmpxchg.h
index 1da5bfbd8c61d135edda020c17724de4ab315ebe..4001d5eab4bb7f1fb59e6e62c924bd71b4b10e2f 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-/* Nonexistent functions intended to cause link errors. */
-extern unsigned long __xchg_called_with_bad_pointer(void);
-extern unsigned long __cmpxchg_called_with_bad_pointer(void);
+#include <asm/barrier.h>
 
-#define xchg(ptr, x)                                                   \
+/* Nonexistent functions intended to cause compile errors. */
+extern void __xchg_called_with_bad_pointer(void)
+       __compiletime_error("Bad argument size for xchg");
+extern void __cmpxchg_called_with_bad_pointer(void)
+       __compiletime_error("Bad argument size for cmpxchg");
+
+#ifndef __tilegx__
+
+/* Note the _atomic_xxx() routines include a final mb(). */
+int _atomic_xchg(int *ptr, int n);
+int _atomic_xchg_add(int *v, int i);
+int _atomic_xchg_add_unless(int *v, int a, int u);
+int _atomic_cmpxchg(int *ptr, int o, int n);
+u64 _atomic64_xchg(u64 *v, u64 n);
+u64 _atomic64_xchg_add(u64 *v, u64 i);
+u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u);
+u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n);
+
+#define xchg(ptr, n)                                                   \
+       ({                                                              \
+               if (sizeof(*(ptr)) != 4)                                \
+                       __xchg_called_with_bad_pointer();               \
+               smp_mb();                                               \
+               (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n));   \
+       })
+
+#define cmpxchg(ptr, o, n)                                             \
+       ({                                                              \
+               if (sizeof(*(ptr)) != 4)                                \
+                       __cmpxchg_called_with_bad_pointer();            \
+               smp_mb();                                               \
+               (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, (int)n); \
+       })
+
+#define xchg64(ptr, n)                                                 \
+       ({                                                              \
+               if (sizeof(*(ptr)) != 8)                                \
+                       __xchg_called_with_bad_pointer();               \
+               smp_mb();                                               \
+               (typeof(*(ptr)))_atomic64_xchg((u64 *)(ptr), (u64)(n)); \
+       })
+
+#define cmpxchg64(ptr, o, n)                                           \
+       ({                                                              \
+               if (sizeof(*(ptr)) != 8)                                \
+                       __cmpxchg_called_with_bad_pointer();            \
+               smp_mb();                                               \
+               (typeof(*(ptr)))_atomic64_cmpxchg((u64 *)ptr, (u64)o, (u64)n); \
+       })
+
+#else
+
+#define xchg(ptr, n)                                                   \
        ({                                                              \
                typeof(*(ptr)) __x;                                     \
+               smp_mb();                                               \
                switch (sizeof(*(ptr))) {                               \
                case 4:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \
-                               (atomic_t *)(ptr),                      \
-                               (u32)(typeof((x)-(x)))(x));             \
+                       __x = (typeof(__x))(unsigned long)              \
+                               __insn_exch4((ptr), (u32)(unsigned long)(n)); \
                        break;                                          \
                case 8:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \
-                               (atomic64_t *)(ptr),                    \
-                               (u64)(typeof((x)-(x)))(x));             \
+                       __x = (typeof(__x))                     \
+                               __insn_exch((ptr), (unsigned long)(n)); \
                        break;                                          \
                default:                                                \
                        __xchg_called_with_bad_pointer();               \
+                       break;                                          \
                }                                                       \
+               smp_mb();                                               \
                __x;                                                    \
        })
 
 #define cmpxchg(ptr, o, n)                                             \
        ({                                                              \
                typeof(*(ptr)) __x;                                     \
+               __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o));    \
+               smp_mb();                                               \
                switch (sizeof(*(ptr))) {                               \
                case 4:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \
-                               (atomic_t *)(ptr),                      \
-                               (u32)(typeof((o)-(o)))(o),              \
-                               (u32)(typeof((n)-(n)))(n));             \
+                       __x = (typeof(__x))(unsigned long)              \
+                               __insn_cmpexch4((ptr), (u32)(unsigned long)(n)); \
                        break;                                          \
                case 8:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \
-                               (atomic64_t *)(ptr),                    \
-                               (u64)(typeof((o)-(o)))(o),              \
-                               (u64)(typeof((n)-(n)))(n));             \
+                       __x = (typeof(__x))__insn_cmpexch((ptr), (u64)(n)); \
                        break;                                          \
                default:                                                \
                        __cmpxchg_called_with_bad_pointer();            \
+                       break;                                          \
                }                                                       \
+               smp_mb();                                               \
                __x;                                                    \
        })
 
-#define tas(ptr) (xchg((ptr), 1))
+#define xchg64 xchg
+#define cmpxchg64 cmpxchg
 
-#define cmpxchg64(ptr, o, n)                                           \
-({                                                                     \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-})
+#endif
+
+#define tas(ptr) xchg((ptr), 1)
 
 #endif /* __ASSEMBLY__ */