1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_SH_ATOMIC_IRQ_H
3 #define __ASM_SH_ATOMIC_IRQ_H
4 
5 #include <linux/irqflags.h>
6 
7 /*
8  * To get proper branch prediction for the main line, we must branch
9  * forward to code at the end of this object's .text section, then
10  * branch back to restart the operation.
11  */
12 
13 #define ATOMIC_OP(op, c_op)						\
14 static inline void atomic_##op(int i, atomic_t *v)			\
15 {									\
16 	unsigned long flags;						\
17 									\
18 	raw_local_irq_save(flags);					\
19 	v->counter c_op i;						\
20 	raw_local_irq_restore(flags);					\
21 }
22 
23 #define ATOMIC_OP_RETURN(op, c_op)					\
24 static inline int atomic_##op##_return(int i, atomic_t *v)		\
25 {									\
26 	unsigned long temp, flags;					\
27 									\
28 	raw_local_irq_save(flags);					\
29 	temp = v->counter;						\
30 	temp c_op i;							\
31 	v->counter = temp;						\
32 	raw_local_irq_restore(flags);					\
33 									\
34 	return temp;							\
35 }
36 
37 #define ATOMIC_FETCH_OP(op, c_op)					\
38 static inline int atomic_fetch_##op(int i, atomic_t *v)			\
39 {									\
40 	unsigned long temp, flags;					\
41 									\
42 	raw_local_irq_save(flags);					\
43 	temp = v->counter;						\
44 	v->counter c_op i;						\
45 	raw_local_irq_restore(flags);					\
46 									\
47 	return temp;							\
48 }
49 
50 #define ATOMIC_OPS(op, c_op)						\
51 	ATOMIC_OP(op, c_op)						\
52 	ATOMIC_OP_RETURN(op, c_op)					\
53 	ATOMIC_FETCH_OP(op, c_op)
54 
55 ATOMIC_OPS(add, +=)
56 ATOMIC_OPS(sub, -=)
57 
58 #undef ATOMIC_OPS
59 #define ATOMIC_OPS(op, c_op)						\
60 	ATOMIC_OP(op, c_op)						\
61 	ATOMIC_FETCH_OP(op, c_op)
62 
63 ATOMIC_OPS(and, &=)
64 ATOMIC_OPS(or, |=)
65 ATOMIC_OPS(xor, ^=)
66 
67 #undef ATOMIC_OPS
68 #undef ATOMIC_FETCH_OP
69 #undef ATOMIC_OP_RETURN
70 #undef ATOMIC_OP
71 
72 #endif /* __ASM_SH_ATOMIC_IRQ_H */
73