Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
d2a5f499 YS |
2 | #ifndef __ARCH_H8300_ATOMIC__ |
3 | #define __ARCH_H8300_ATOMIC__ | |
4 | ||
5 | #include <linux/types.h> | |
6 | #include <asm/cmpxchg.h> | |
7 | ||
8 | /* | |
9 | * Atomic operations that C can't guarantee us. Useful for | |
10 | * resource counting etc.. | |
11 | */ | |
12 | ||
13 | #define ATOMIC_INIT(i) { (i) } | |
14 | ||
62e8a325 PZ |
15 | #define atomic_read(v) READ_ONCE((v)->counter) |
16 | #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) | |
d2a5f499 YS |
17 | |
18 | #include <linux/kernel.h> | |
19 | ||
73ada370 PZ |
20 | #define ATOMIC_OP_RETURN(op, c_op) \ |
21 | static inline int atomic_##op##_return(int i, atomic_t *v) \ | |
22 | { \ | |
23 | h8300flags flags; \ | |
24 | int ret; \ | |
25 | \ | |
26 | flags = arch_local_irq_save(); \ | |
27 | ret = v->counter c_op i; \ | |
28 | arch_local_irq_restore(flags); \ | |
29 | return ret; \ | |
d2a5f499 YS |
30 | } |
31 | ||
0c074cbc PZ |
32 | #define ATOMIC_FETCH_OP(op, c_op) \ |
33 | static inline int atomic_fetch_##op(int i, atomic_t *v) \ | |
34 | { \ | |
35 | h8300flags flags; \ | |
36 | int ret; \ | |
37 | \ | |
38 | flags = arch_local_irq_save(); \ | |
39 | ret = v->counter; \ | |
40 | v->counter c_op i; \ | |
41 | arch_local_irq_restore(flags); \ | |
42 | return ret; \ | |
43 | } | |
44 | ||
73ada370 PZ |
45 | #define ATOMIC_OP(op, c_op) \ |
46 | static inline void atomic_##op(int i, atomic_t *v) \ | |
47 | { \ | |
48 | h8300flags flags; \ | |
49 | \ | |
50 | flags = arch_local_irq_save(); \ | |
51 | v->counter c_op i; \ | |
52 | arch_local_irq_restore(flags); \ | |
d2a5f499 YS |
53 | } |
54 | ||
73ada370 PZ |
55 | ATOMIC_OP_RETURN(add, +=) |
56 | ATOMIC_OP_RETURN(sub, -=) | |
d2a5f499 | 57 | |
0c074cbc PZ |
58 | #define ATOMIC_OPS(op, c_op) \ |
59 | ATOMIC_OP(op, c_op) \ | |
60 | ATOMIC_FETCH_OP(op, c_op) | |
61 | ||
62 | ATOMIC_OPS(and, &=) | |
63 | ATOMIC_OPS(or, |=) | |
64 | ATOMIC_OPS(xor, ^=) | |
65 | ATOMIC_OPS(add, +=) | |
66 | ATOMIC_OPS(sub, -=) | |
67 | ||
68 | #undef ATOMIC_OPS | |
73ada370 PZ |
69 | #undef ATOMIC_OP_RETURN |
70 | #undef ATOMIC_OP | |
d2a5f499 | 71 | |
73ada370 | 72 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) |
73ada370 | 73 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) |
d2a5f499 | 74 | |
73ada370 PZ |
75 | #define atomic_inc_return(v) atomic_add_return(1, v) |
76 | #define atomic_dec_return(v) atomic_sub_return(1, v) | |
d2a5f499 | 77 | |
73ada370 PZ |
78 | #define atomic_inc(v) (void)atomic_inc_return(v) |
79 | #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) | |
d2a5f499 | 80 | |
73ada370 PZ |
81 | #define atomic_dec(v) (void)atomic_dec_return(v) |
82 | #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) | |
d2a5f499 YS |
83 | |
84 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | |
85 | { | |
86 | int ret; | |
87 | h8300flags flags; | |
88 | ||
89 | flags = arch_local_irq_save(); | |
90 | ret = v->counter; | |
91 | if (likely(ret == old)) | |
92 | v->counter = new; | |
93 | arch_local_irq_restore(flags); | |
94 | return ret; | |
95 | } | |
96 | ||
97 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) | |
98 | { | |
99 | int ret; | |
100 | h8300flags flags; | |
101 | ||
102 | flags = arch_local_irq_save(); | |
103 | ret = v->counter; | |
104 | if (ret != u) | |
105 | v->counter += a; | |
106 | arch_local_irq_restore(flags); | |
107 | return ret; | |
108 | } | |
109 | ||
d2a5f499 | 110 | #endif /* __ARCH_H8300_ATOMIC __ */ |