diff options
author | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-09-27 11:56:14 -0300 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-09-27 11:56:14 -0300 |
commit | 1025c04cecd19882e28f16c4004034b475c372c5 (patch) | |
tree | 2b7402887e86d54bff5a123228c9059eae5e32bd /arch/tile/include/asm/cmpxchg.h | |
parent | 4375f1037d52602413142e290608d0d84671ad36 (diff) | |
parent | 5bcecf325378218a8e248bb6bcae96ec7362f8ef (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Conflicts:
net/bluetooth/hci_core.c
Diffstat (limited to 'arch/tile/include/asm/cmpxchg.h')
-rw-r--r-- | arch/tile/include/asm/cmpxchg.h | 93 |
1 files changed, 74 insertions, 19 deletions
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h index 276f067e364..4001d5eab4b 100644 --- a/arch/tile/include/asm/cmpxchg.h +++ b/arch/tile/include/asm/cmpxchg.h @@ -20,53 +20,108 @@ #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 + +#endif + +#define tas(ptr) xchg((ptr), 1) #endif /* __ASSEMBLY__ */ |