Commit 8263db4d authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

MIPS: cmpxchg: Implement __cmpxchg() as a function

Replace the macro definition of __cmpxchg() with an inline function,
which is easier to read & modify. The cmpxchg() & cmpxchg_local() macros
are adjusted to call the new __cmpxchg() function.
Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16353/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 62c6081d
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* *
* - Get an error at link-time due to the call to the missing function. * - Get an error at link-time due to the call to the missing function.
*/ */
extern void __cmpxchg_called_with_bad_pointer(void) extern unsigned long __cmpxchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for cmpxchg"); __compiletime_error("Bad argument size for cmpxchg");
extern unsigned long __xchg_called_with_bad_pointer(void) extern unsigned long __xchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for xchg"); __compiletime_error("Bad argument size for xchg");
...@@ -137,38 +137,43 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -137,38 +137,43 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
__ret; \ __ret; \
}) })
#define __cmpxchg(ptr, old, new, pre_barrier, post_barrier) \ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, unsigned int size)
{
switch (size) {
case 4:
return __cmpxchg_asm("ll", "sc", (volatile u32 *)ptr, old, new);
case 8:
/* lld/scd are only available for MIPS64 */
if (!IS_ENABLED(CONFIG_64BIT))
return __cmpxchg_called_with_bad_pointer();
return __cmpxchg_asm("lld", "scd", (volatile u64 *)ptr, old, new);
default:
return __cmpxchg_called_with_bad_pointer();
}
}
#define cmpxchg_local(ptr, old, new) \
((__typeof__(*(ptr))) \
__cmpxchg((ptr), \
(unsigned long)(__typeof__(*(ptr)))(old), \
(unsigned long)(__typeof__(*(ptr)))(new), \
sizeof(*(ptr))))
#define cmpxchg(ptr, old, new) \
({ \ ({ \
__typeof__(ptr) __ptr = (ptr); \ __typeof__(*(ptr)) __res; \
__typeof__(*(ptr)) __old = (old); \
__typeof__(*(ptr)) __new = (new); \
__typeof__(*(ptr)) __res = 0; \
\
pre_barrier; \
\
switch (sizeof(*(__ptr))) { \
case 4: \
__res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new); \
break; \
case 8: \
if (sizeof(long) == 8) { \
__res = __cmpxchg_asm("lld", "scd", __ptr, \
__old, __new); \
break; \
} \
default: \
__cmpxchg_called_with_bad_pointer(); \
break; \
} \
\ \
post_barrier; \ smp_mb__before_llsc(); \
__res = cmpxchg_local((ptr), (old), (new)); \
smp_llsc_mb(); \
\ \
__res; \ __res; \
}) })
#define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new, smp_mb__before_llsc(), smp_llsc_mb())
#define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new, , )
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define cmpxchg64_local(ptr, o, n) \ #define cmpxchg64_local(ptr, o, n) \
({ \ ({ \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment