From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> Remove cmpxchg_small and xchg_small, because it's unnecessary now, and they break the forward guarantee for atomic operations. Also Remove unnecessary __HAVE_ARCH_CMPXCHG. Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> Signed-off-by: Guo Ren <guoren@xxxxxxxxxx> Cc: Stafford Horne <shorne@xxxxxxxxx> Cc: Jonas Bonn <jonas@xxxxxxxxxxxx> Cc: Stefan Kristiansson <stefan.kristiansson@xxxxxxxxxxxxx> --- arch/openrisc/include/asm/cmpxchg.h | 167 +++++++++------------------- 1 file changed, 50 insertions(+), 117 deletions(-) diff --git a/arch/openrisc/include/asm/cmpxchg.h b/arch/openrisc/include/asm/cmpxchg.h index 79fd16162ccb..df83b33b5882 100644 --- a/arch/openrisc/include/asm/cmpxchg.h +++ b/arch/openrisc/include/asm/cmpxchg.h @@ -20,10 +20,8 @@ #include <linux/compiler.h> #include <linux/types.h> -#define __HAVE_ARCH_CMPXCHG 1 - -static inline unsigned long cmpxchg_u32(volatile void *ptr, - unsigned long old, unsigned long new) +/* cmpxchg */ +static inline u32 cmpxchg32(volatile void *ptr, u32 old, u32 new) { __asm__ __volatile__( "1: l.lwa %0, 0(%1) \n" @@ -41,8 +39,33 @@ static inline unsigned long cmpxchg_u32(volatile void *ptr, return old; } -static inline unsigned long xchg_u32(volatile void *ptr, - unsigned long val) +#define __cmpxchg(ptr, old, new, size) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(*(ptr)) __old = (old); \ + __typeof__(*(ptr)) __new = (new); \ + __typeof__(*(ptr)) __ret; \ + switch (size) { \ + case 4: \ + __ret = (__typeof__(*(ptr))) \ + cmpxchg32(__ptr, (u32)__old, (u32)__new); \ + break; \ + default: \ + BUILD_BUG(); \ + } \ + __ret; \ +}) + +#define arch_cmpxchg(ptr, o, n) \ +({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), \ + _o_, _n_, sizeof(*(ptr))); \ +}) + +/* xchg */ +static inline u32 xchg32(volatile void *ptr, u32 val) { __asm__ __volatile__( "1: l.lwa %0, 0(%1) \n" @@ -56,116 +79,26 @@ static inline unsigned long xchg_u32(volatile void *ptr, return val; } -static inline u32 cmpxchg_small(volatile void *ptr, u32 old, u32 new, - int size) -{ - int off = (unsigned long)ptr % sizeof(u32); - volatile u32 *p = ptr - off; -#ifdef __BIG_ENDIAN - int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE; -#else - int bitoff = off * BITS_PER_BYTE; -#endif - u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff; - u32 load32, old32, new32; - u32 ret; - - load32 = READ_ONCE(*p); - - while (true) { - ret = (load32 & bitmask) >> bitoff; - if (old != ret) - return ret; - - old32 = (load32 & ~bitmask) | (old << bitoff); - new32 = (load32 & ~bitmask) | (new << bitoff); - - /* Do 32 bit cmpxchg */ - load32 = cmpxchg_u32(p, old32, new32); - if (load32 == old32) - return old; - } -} - -/* xchg */ - -static inline u32 xchg_small(volatile void *ptr, u32 x, int size) -{ - int off = (unsigned long)ptr % sizeof(u32); - volatile u32 *p = ptr - off; -#ifdef __BIG_ENDIAN - int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE; -#else - int bitoff = off * BITS_PER_BYTE; -#endif - u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff; - u32 oldv, newv; - u32 ret; - - do { - oldv = READ_ONCE(*p); - ret = (oldv & bitmask) >> bitoff; - newv = (oldv & ~bitmask) | (x << bitoff); - } while (cmpxchg_u32(p, oldv, newv) != oldv); - - return ret; -} - -/* - * This function doesn't exist, so you'll get a linker error - * if something tries to do an invalid cmpxchg(). - */ -extern unsigned long __cmpxchg_called_with_bad_pointer(void) - __compiletime_error("Bad argument size for cmpxchg"); - -static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 1: - case 2: - return cmpxchg_small(ptr, old, new, size); - case 4: - return cmpxchg_u32(ptr, old, new); - default: - return __cmpxchg_called_with_bad_pointer(); - } -} - -#define arch_cmpxchg(ptr, o, n) \ - ({ \ - (__typeof__(*(ptr))) __cmpxchg((ptr), \ - (unsigned long)(o), \ - (unsigned long)(n), \ - sizeof(*(ptr))); \ - }) - -/* - * This function doesn't exist, so you'll get a linker error if - * something tries to do an invalidly-sized xchg(). - */ -extern unsigned long __xchg_called_with_bad_pointer(void) - __compiletime_error("Bad argument size for xchg"); - -static inline unsigned long __xchg(volatile void *ptr, unsigned long with, - int size) -{ - switch (size) { - case 1: - case 2: - return xchg_small(ptr, with, size); - case 4: - return xchg_u32(ptr, with); - default: - return __xchg_called_with_bad_pointer(); - } -} - -#define arch_xchg(ptr, with) \ - ({ \ - (__typeof__(*(ptr))) __xchg((ptr), \ - (unsigned long)(with), \ - sizeof(*(ptr))); \ - }) +#define __xchg(ptr, new, size) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(new) __new = (new); \ + __typeof__(*(ptr)) __ret; \ + switch (size) { \ + case 4: \ + __ret = (__typeof__(*(ptr))) \ + xchg32(__ptr, (u32)__new); \ + break; \ + default: \ + BUILD_BUG(); \ + } \ + __ret; \ +}) + +#define arch_xchg(ptr, x) \ +({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg((ptr), _x_, sizeof(*(ptr))); \ +}) #endif /* __ASM_OPENRISC_CMPXCHG_H */ -- 2.36.1