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