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