^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef __ASM_SH_CMPXCHG_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define __ASM_SH_CMPXCHG_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Atomic operations that C can't guarantee us. Useful for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * resource counting etc..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #if defined(CONFIG_GUSA_RB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/cmpxchg-grb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #elif defined(CONFIG_CPU_SH4A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/cmpxchg-llsc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cmpxchg-cas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cmpxchg-irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) extern void __xchg_called_with_bad_pointer(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define __xchg(ptr, x, size) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long __xchg__res; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) volatile void *__xchg_ptr = (ptr); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) switch (size) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) case 4: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) __xchg__res = xchg_u32(__xchg_ptr, x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case 2: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __xchg__res = xchg_u16(__xchg_ptr, x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case 1: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) __xchg__res = xchg_u8(__xchg_ptr, x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) default: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) __xchg_called_with_bad_pointer(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) __xchg__res = x; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) break; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) __xchg__res; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define xchg(ptr,x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* This function doesn't exist, so you'll get a linker error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * if something tries to do an invalid cmpxchg(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) extern void __cmpxchg_called_with_bad_pointer(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long new, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return __cmpxchg_u32(ptr, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) __cmpxchg_called_with_bad_pointer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define cmpxchg(ptr,o,n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) __typeof__(*(ptr)) _o_ = (o); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) __typeof__(*(ptr)) _n_ = (n); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) (unsigned long)_n_, sizeof(*(ptr))); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif /* __ASM_SH_CMPXCHG_H */