1/* SPDX-License-Identifier: GPL-2.0+ */
2
3#ifndef _ASM_GENERIC_ATOMIC_H
4#define _ASM_GENERIC_ATOMIC_H
5
6typedef struct { volatile int counter; } atomic_t;
7#if BITS_PER_LONG == 32
8typedef struct { volatile long long counter; } atomic64_t;
9#else /* BIT_PER_LONG == 32 */
10typedef struct { volatile long counter; } atomic64_t;
11#endif
12
13#define ATOMIC_INIT(i)	{ (i) }
14
15#define atomic_read(v)		((v)->counter)
16#define atomic_set(v, i)	((v)->counter = (i))
17#define atomic64_read(v)	atomic_read(v)
18#define atomic64_set(v, i)	atomic_set(v, i)
19
20static inline void atomic_add(int i, atomic_t *v)
21{
22	unsigned long flags = 0;
23
24	local_irq_save(flags);
25	v->counter += i;
26	local_irq_restore(flags);
27}
28
29static inline void atomic_sub(int i, atomic_t *v)
30{
31	unsigned long flags = 0;
32
33	local_irq_save(flags);
34	v->counter -= i;
35	local_irq_restore(flags);
36}
37
38static inline void atomic_inc(atomic_t *v)
39{
40	unsigned long flags = 0;
41
42	local_irq_save(flags);
43	++v->counter;
44	local_irq_restore(flags);
45}
46
47static inline void atomic_dec(atomic_t *v)
48{
49	unsigned long flags = 0;
50
51	local_irq_save(flags);
52	--v->counter;
53	local_irq_restore(flags);
54}
55
56static inline int atomic_dec_and_test(volatile atomic_t *v)
57{
58	unsigned long flags = 0;
59	int val;
60
61	local_irq_save(flags);
62	val = v->counter;
63	v->counter = val -= 1;
64	local_irq_restore(flags);
65
66	return val == 0;
67}
68
69static inline int atomic_add_negative(int i, volatile atomic_t *v)
70{
71	unsigned long flags = 0;
72	int val;
73
74	local_irq_save(flags);
75	val = v->counter;
76	v->counter = val += i;
77	local_irq_restore(flags);
78
79	return val < 0;
80}
81
82static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
83{
84	unsigned long flags = 0;
85
86	local_irq_save(flags);
87	*addr &= ~mask;
88	local_irq_restore(flags);
89}
90
91#if BITS_PER_LONG == 32
92
93static inline void atomic64_add(long long i, volatile atomic64_t *v)
94{
95	unsigned long flags = 0;
96
97	local_irq_save(flags);
98	v->counter += i;
99	local_irq_restore(flags);
100}
101
102static inline void atomic64_sub(long long i, volatile atomic64_t *v)
103{
104	unsigned long flags = 0;
105
106	local_irq_save(flags);
107	v->counter -= i;
108	local_irq_restore(flags);
109}
110
111#else /* BIT_PER_LONG == 32 */
112
113static inline void atomic64_add(long i, volatile atomic64_t *v)
114{
115	unsigned long flags = 0;
116
117	local_irq_save(flags);
118	v->counter += i;
119	local_irq_restore(flags);
120}
121
122static inline void atomic64_sub(long i, volatile atomic64_t *v)
123{
124	unsigned long flags = 0;
125
126	local_irq_save(flags);
127	v->counter -= i;
128	local_irq_restore(flags);
129}
130#endif
131
132static inline void atomic64_inc(volatile atomic64_t *v)
133{
134	unsigned long flags = 0;
135
136	local_irq_save(flags);
137	v->counter += 1;
138	local_irq_restore(flags);
139}
140
141static inline void atomic64_dec(volatile atomic64_t *v)
142{
143	unsigned long flags = 0;
144
145	local_irq_save(flags);
146	v->counter -= 1;
147	local_irq_restore(flags);
148}
149
150#endif
151