1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#ifndef __ASM_ARM_BITOPS_H
18#define __ASM_ARM_BITOPS_H
19
20#ifdef __KERNEL__
21
22#ifndef _LINUX_BITOPS_H
23#error only <linux/bitops.h> can be included directly
24#endif
25
26#include <linux/compiler.h>
27#include <linux/irqflags.h>
28#include <asm/barrier.h>
29
30
31
32
33
34
35static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
36{
37 unsigned long flags;
38 unsigned long mask = BIT_MASK(bit);
39
40 p += BIT_WORD(bit);
41
42 raw_local_irq_save(flags);
43 *p |= mask;
44 raw_local_irq_restore(flags);
45}
46
47static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
48{
49 unsigned long flags;
50 unsigned long mask = BIT_MASK(bit);
51
52 p += BIT_WORD(bit);
53
54 raw_local_irq_save(flags);
55 *p &= ~mask;
56 raw_local_irq_restore(flags);
57}
58
59static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
60{
61 unsigned long flags;
62 unsigned long mask = BIT_MASK(bit);
63
64 p += BIT_WORD(bit);
65
66 raw_local_irq_save(flags);
67 *p ^= mask;
68 raw_local_irq_restore(flags);
69}
70
71static inline int
72____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
73{
74 unsigned long flags;
75 unsigned int res;
76 unsigned long mask = BIT_MASK(bit);
77
78 p += BIT_WORD(bit);
79
80 raw_local_irq_save(flags);
81 res = *p;
82 *p = res | mask;
83 raw_local_irq_restore(flags);
84
85 return (res & mask) != 0;
86}
87
88static inline int
89____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
90{
91 unsigned long flags;
92 unsigned int res;
93 unsigned long mask = BIT_MASK(bit);
94
95 p += BIT_WORD(bit);
96
97 raw_local_irq_save(flags);
98 res = *p;
99 *p = res & ~mask;
100 raw_local_irq_restore(flags);
101
102 return (res & mask) != 0;
103}
104
105static inline int
106____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
107{
108 unsigned long flags;
109 unsigned int res;
110 unsigned long mask = BIT_MASK(bit);
111
112 p += BIT_WORD(bit);
113
114 raw_local_irq_save(flags);
115 res = *p;
116 *p = res ^ mask;
117 raw_local_irq_restore(flags);
118
119 return (res & mask) != 0;
120}
121
122#include <asm-generic/bitops/non-atomic.h>
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152extern void _set_bit(int nr, volatile unsigned long * p);
153extern void _clear_bit(int nr, volatile unsigned long * p);
154extern void _change_bit(int nr, volatile unsigned long * p);
155extern int _test_and_set_bit(int nr, volatile unsigned long * p);
156extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
157extern int _test_and_change_bit(int nr, volatile unsigned long * p);
158
159
160
161
162extern int _find_first_zero_bit_le(const void * p, unsigned size);
163extern int _find_next_zero_bit_le(const void * p, int size, int offset);
164extern int _find_first_bit_le(const unsigned long *p, unsigned size);
165extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
166
167
168
169
170extern int _find_first_zero_bit_be(const void * p, unsigned size);
171extern int _find_next_zero_bit_be(const void * p, int size, int offset);
172extern int _find_first_bit_be(const unsigned long *p, unsigned size);
173extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
174
175#ifndef CONFIG_SMP
176
177
178
179#define ATOMIC_BITOP(name,nr,p) \
180 (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
181#else
182#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
183#endif
184
185
186
187
188#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
189#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p)
190#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p)
191#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p)
192#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p)
193#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p)
194
195#ifndef __ARMEB__
196
197
198
199#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
200#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
201#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
202#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off)
203
204#else
205
206
207
208#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
209#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
210#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
211#define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off)
212
213#endif
214
215#if __LINUX_ARM_ARCH__ < 5
216
217#include <asm-generic/bitops/ffz.h>
218#include <asm-generic/bitops/__fls.h>
219#include <asm-generic/bitops/__ffs.h>
220#include <asm-generic/bitops/fls.h>
221#include <asm-generic/bitops/ffs.h>
222
223#else
224
225static inline int constant_fls(int x)
226{
227 int r = 32;
228
229 if (!x)
230 return 0;
231 if (!(x & 0xffff0000u)) {
232 x <<= 16;
233 r -= 16;
234 }
235 if (!(x & 0xff000000u)) {
236 x <<= 8;
237 r -= 8;
238 }
239 if (!(x & 0xf0000000u)) {
240 x <<= 4;
241 r -= 4;
242 }
243 if (!(x & 0xc0000000u)) {
244 x <<= 2;
245 r -= 2;
246 }
247 if (!(x & 0x80000000u)) {
248 x <<= 1;
249 r -= 1;
250 }
251 return r;
252}
253
254
255
256
257
258
259
260static inline unsigned int __clz(unsigned int x)
261{
262 unsigned int ret;
263
264 asm("clz\t%0, %1" : "=r" (ret) : "r" (x));
265
266 return ret;
267}
268
269
270
271
272
273static inline int fls(int x)
274{
275 if (__builtin_constant_p(x))
276 return constant_fls(x);
277
278 return 32 - __clz(x);
279}
280
281
282
283
284
285static inline unsigned long __fls(unsigned long x)
286{
287 return fls(x) - 1;
288}
289
290
291
292
293
294static inline int ffs(int x)
295{
296 return fls(x & -x);
297}
298
299
300
301
302
303static inline unsigned long __ffs(unsigned long x)
304{
305 return ffs(x) - 1;
306}
307
308#define ffz(x) __ffs( ~(x) )
309
310#endif
311
312#include <asm-generic/bitops/fls64.h>
313
314#include <asm-generic/bitops/sched.h>
315#include <asm-generic/bitops/hweight.h>
316#include <asm-generic/bitops/lock.h>
317
318#ifdef __ARMEB__
319
320static inline int find_first_zero_bit_le(const void *p, unsigned size)
321{
322 return _find_first_zero_bit_le(p, size);
323}
324#define find_first_zero_bit_le find_first_zero_bit_le
325
326static inline int find_next_zero_bit_le(const void *p, int size, int offset)
327{
328 return _find_next_zero_bit_le(p, size, offset);
329}
330#define find_next_zero_bit_le find_next_zero_bit_le
331
332static inline int find_next_bit_le(const void *p, int size, int offset)
333{
334 return _find_next_bit_le(p, size, offset);
335}
336#define find_next_bit_le find_next_bit_le
337
338#endif
339
340#include <asm-generic/bitops/le.h>
341
342
343
344
345#include <asm-generic/bitops/ext2-atomic-setbit.h>
346
347#endif
348
349#endif
350