xref: /linux/arch/sh/include/asm/cmpxchg.h (revision 980bcd35ae0a21da9a22155e386c8ff17019d545)
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>
12*c81a748eSPaul E. McKenney #include <linux/cmpxchg-emu.h>
13e839ca52SDavid Howells 
14e839ca52SDavid Howells #if defined(CONFIG_GUSA_RB)
15e839ca52SDavid Howells #include <asm/cmpxchg-grb.h>
16e839ca52SDavid Howells #elif defined(CONFIG_CPU_SH4A)
17e839ca52SDavid Howells #include <asm/cmpxchg-llsc.h>
182b47d54eSRich Felker #elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
192b47d54eSRich Felker #include <asm/cmpxchg-cas.h>
20e839ca52SDavid Howells #else
21e839ca52SDavid Howells #include <asm/cmpxchg-irq.h>
22e839ca52SDavid Howells #endif
23e839ca52SDavid Howells 
24e839ca52SDavid Howells extern void __xchg_called_with_bad_pointer(void);
25e839ca52SDavid Howells 
2606855063SAndrzej Hajda #define __arch_xchg(ptr, x, size)				\
27e839ca52SDavid Howells ({							\
28e839ca52SDavid Howells 	unsigned long __xchg__res;			\
29e839ca52SDavid Howells 	volatile void *__xchg_ptr = (ptr);		\
30e839ca52SDavid Howells 	switch (size) {					\
31e839ca52SDavid Howells 	case 4:						\
32e839ca52SDavid Howells 		__xchg__res = xchg_u32(__xchg_ptr, x);	\
33e839ca52SDavid Howells 		break;					\
343226aad8SMichael S. Tsirkin 	case 2:						\
353226aad8SMichael S. Tsirkin 		__xchg__res = xchg_u16(__xchg_ptr, x);	\
363226aad8SMichael S. Tsirkin 		break;					\
37e839ca52SDavid Howells 	case 1:						\
38e839ca52SDavid Howells 		__xchg__res = xchg_u8(__xchg_ptr, x);	\
39e839ca52SDavid Howells 		break;					\
40e839ca52SDavid Howells 	default:					\
41e839ca52SDavid Howells 		__xchg_called_with_bad_pointer();	\
42e839ca52SDavid Howells 		__xchg__res = x;			\
43e839ca52SDavid Howells 		break;					\
44e839ca52SDavid Howells 	}						\
45e839ca52SDavid Howells 							\
46e839ca52SDavid Howells 	__xchg__res;					\
47e839ca52SDavid Howells })
48e839ca52SDavid Howells 
498c641755SMark Rutland #define arch_xchg(ptr,x)	\
5006855063SAndrzej Hajda 	((__typeof__(*(ptr)))__arch_xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
51e839ca52SDavid Howells 
52e839ca52SDavid Howells /* This function doesn't exist, so you'll get a linker error
53e839ca52SDavid Howells  * if something tries to do an invalid cmpxchg(). */
54e839ca52SDavid Howells extern void __cmpxchg_called_with_bad_pointer(void);
55e839ca52SDavid Howells 
__cmpxchg(volatile void * ptr,unsigned long old,unsigned long new,int size)56e839ca52SDavid Howells static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
57e839ca52SDavid Howells 		unsigned long new, int size)
58e839ca52SDavid Howells {
59e839ca52SDavid Howells 	switch (size) {
60*c81a748eSPaul E. McKenney 	case 1:
61*c81a748eSPaul E. McKenney 		return cmpxchg_emu_u8(ptr, old, new);
62e839ca52SDavid Howells 	case 4:
63e839ca52SDavid Howells 		return __cmpxchg_u32(ptr, old, new);
64e839ca52SDavid Howells 	}
65e839ca52SDavid Howells 	__cmpxchg_called_with_bad_pointer();
66e839ca52SDavid Howells 	return old;
67e839ca52SDavid Howells }
68e839ca52SDavid Howells 
698c641755SMark Rutland #define arch_cmpxchg(ptr,o,n)						 \
70e839ca52SDavid Howells   ({									 \
71e839ca52SDavid Howells      __typeof__(*(ptr)) _o_ = (o);					 \
72e839ca52SDavid Howells      __typeof__(*(ptr)) _n_ = (n);					 \
73e839ca52SDavid Howells      (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
74e839ca52SDavid Howells 				    (unsigned long)_n_, sizeof(*(ptr))); \
75e839ca52SDavid Howells   })
76e839ca52SDavid Howells 
7763f1ee20SMasami Hiramatsu #include <asm-generic/cmpxchg-local.h>
7863f1ee20SMasami Hiramatsu 
7963f1ee20SMasami Hiramatsu #define arch_cmpxchg_local(ptr, o, n) ({				\
8063f1ee20SMasami Hiramatsu 	(__typeof__(*ptr))__generic_cmpxchg_local((ptr),		\
8163f1ee20SMasami Hiramatsu 						  (unsigned long)(o),	\
8263f1ee20SMasami Hiramatsu 						  (unsigned long)(n),	\
8363f1ee20SMasami Hiramatsu 						  sizeof(*(ptr)));	\
8463f1ee20SMasami Hiramatsu })
8563f1ee20SMasami Hiramatsu 
86e839ca52SDavid Howells #endif /* __ASM_SH_CMPXCHG_H */
87