Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+32 −27
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@
 *
 * - 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");
extern unsigned long __xchg_called_with_bad_pointer(void)
	__compiletime_error("Bad argument size for xchg");
@@ -137,38 +137,43 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
	__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)) __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;							\
	}								\
	__typeof__(*(ptr)) __res;					\
									\
	post_barrier;							\
	smp_mb__before_llsc();						\
	__res = cmpxchg_local((ptr), (old), (new));			\
	smp_llsc_mb();							\
									\
	__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
#define cmpxchg64_local(ptr, o, n)					\
  ({									\