Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
c7f612cd AM |
2 | #ifndef _ASM_GENERIC_BITOPS_FIND_H_ |
3 | #define _ASM_GENERIC_BITOPS_FIND_H_ | |
4 | ||
5c88af59 YN |
5 | extern unsigned long _find_next_bit(const unsigned long *addr1, |
6 | const unsigned long *addr2, unsigned long nbits, | |
7 | unsigned long start, unsigned long invert, unsigned long le); | |
2cc7b6a4 YN |
8 | extern unsigned long _find_first_bit(const unsigned long *addr, unsigned long size); |
9 | extern unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned long size); | |
10 | extern unsigned long _find_last_bit(const unsigned long *addr, unsigned long size); | |
5c88af59 | 11 | |
19de85ef | 12 | #ifndef find_next_bit |
d852a6af AM |
13 | /** |
14 | * find_next_bit - find the next set bit in a memory region | |
15 | * @addr: The address to base the search on | |
16 | * @offset: The bitnumber to start searching at | |
17 | * @size: The bitmap size in bits | |
ec778edf CS |
18 | * |
19 | * Returns the bit number for the next set bit | |
20 | * If no bits are set, returns @size. | |
d852a6af | 21 | */ |
5c88af59 YN |
22 | static inline |
23 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | |
24 | unsigned long offset) | |
25 | { | |
277a20a4 YN |
26 | if (small_const_nbits(size)) { |
27 | unsigned long val; | |
28 | ||
29 | if (unlikely(offset >= size)) | |
30 | return size; | |
31 | ||
32 | val = *addr & GENMASK(size - 1, offset); | |
33 | return val ? __ffs(val) : size; | |
34 | } | |
35 | ||
5c88af59 YN |
36 | return _find_next_bit(addr, NULL, size, offset, 0UL, 0); |
37 | } | |
19de85ef | 38 | #endif |
c7f612cd | 39 | |
0ade34c3 CC |
40 | #ifndef find_next_and_bit |
41 | /** | |
42 | * find_next_and_bit - find the next set bit in both memory regions | |
43 | * @addr1: The first address to base the search on | |
44 | * @addr2: The second address to base the search on | |
45 | * @offset: The bitnumber to start searching at | |
46 | * @size: The bitmap size in bits | |
47 | * | |
48 | * Returns the bit number for the next set bit | |
49 | * If no bits are set, returns @size. | |
50 | */ | |
5c88af59 YN |
51 | static inline |
52 | unsigned long find_next_and_bit(const unsigned long *addr1, | |
0ade34c3 | 53 | const unsigned long *addr2, unsigned long size, |
5c88af59 YN |
54 | unsigned long offset) |
55 | { | |
277a20a4 YN |
56 | if (small_const_nbits(size)) { |
57 | unsigned long val; | |
58 | ||
59 | if (unlikely(offset >= size)) | |
60 | return size; | |
61 | ||
62 | val = *addr1 & *addr2 & GENMASK(size - 1, offset); | |
63 | return val ? __ffs(val) : size; | |
64 | } | |
65 | ||
5c88af59 YN |
66 | return _find_next_bit(addr1, addr2, size, offset, 0UL, 0); |
67 | } | |
0ade34c3 CC |
68 | #endif |
69 | ||
19de85ef | 70 | #ifndef find_next_zero_bit |
d852a6af AM |
71 | /** |
72 | * find_next_zero_bit - find the next cleared bit in a memory region | |
73 | * @addr: The address to base the search on | |
74 | * @offset: The bitnumber to start searching at | |
75 | * @size: The bitmap size in bits | |
ec778edf CS |
76 | * |
77 | * Returns the bit number of the next zero bit | |
78 | * If no bits are zero, returns @size. | |
d852a6af | 79 | */ |
5c88af59 YN |
80 | static inline |
81 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, | |
82 | unsigned long offset) | |
83 | { | |
277a20a4 YN |
84 | if (small_const_nbits(size)) { |
85 | unsigned long val; | |
86 | ||
87 | if (unlikely(offset >= size)) | |
88 | return size; | |
89 | ||
90 | val = *addr | ~GENMASK(size - 1, offset); | |
91 | return val == ~0UL ? size : ffz(val); | |
92 | } | |
93 | ||
5c88af59 YN |
94 | return _find_next_bit(addr, NULL, size, offset, ~0UL, 0); |
95 | } | |
19de85ef | 96 | #endif |
c7f612cd | 97 | |
708ff2a0 AM |
98 | #ifdef CONFIG_GENERIC_FIND_FIRST_BIT |
99 | ||
100 | /** | |
101 | * find_first_bit - find the first set bit in a memory region | |
102 | * @addr: The address to start the search at | |
ec778edf | 103 | * @size: The maximum number of bits to search |
708ff2a0 AM |
104 | * |
105 | * Returns the bit number of the first set bit. | |
ec778edf | 106 | * If no bits are set, returns @size. |
708ff2a0 | 107 | */ |
2cc7b6a4 YN |
108 | static inline |
109 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) | |
110 | { | |
111 | if (small_const_nbits(size)) { | |
112 | unsigned long val = *addr & GENMASK(size - 1, 0); | |
113 | ||
114 | return val ? __ffs(val) : size; | |
115 | } | |
116 | ||
117 | return _find_first_bit(addr, size); | |
118 | } | |
708ff2a0 AM |
119 | |
120 | /** | |
121 | * find_first_zero_bit - find the first cleared bit in a memory region | |
122 | * @addr: The address to start the search at | |
ec778edf | 123 | * @size: The maximum number of bits to search |
708ff2a0 AM |
124 | * |
125 | * Returns the bit number of the first cleared bit. | |
ec778edf | 126 | * If no bits are zero, returns @size. |
708ff2a0 | 127 | */ |
2cc7b6a4 YN |
128 | static inline |
129 | unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) | |
130 | { | |
131 | if (small_const_nbits(size)) { | |
132 | unsigned long val = *addr | ~GENMASK(size - 1, 0); | |
133 | ||
134 | return val == ~0UL ? size : ffz(val); | |
135 | } | |
136 | ||
137 | return _find_first_zero_bit(addr, size); | |
138 | } | |
708ff2a0 AM |
139 | #else /* CONFIG_GENERIC_FIND_FIRST_BIT */ |
140 | ||
0ade34c3 | 141 | #ifndef find_first_bit |
c7f612cd | 142 | #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) |
0ade34c3 CC |
143 | #endif |
144 | #ifndef find_first_zero_bit | |
c7f612cd | 145 | #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) |
0ade34c3 | 146 | #endif |
c7f612cd | 147 | |
708ff2a0 AM |
148 | #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ |
149 | ||
2cc7b6a4 YN |
150 | #ifndef find_last_bit |
151 | /** | |
152 | * find_last_bit - find the last set bit in a memory region | |
153 | * @addr: The address to start the search at | |
154 | * @size: The number of bits to search | |
155 | * | |
156 | * Returns the bit number of the last set bit, or size. | |
157 | */ | |
158 | static inline | |
159 | unsigned long find_last_bit(const unsigned long *addr, unsigned long size) | |
160 | { | |
161 | if (small_const_nbits(size)) { | |
162 | unsigned long val = *addr & GENMASK(size - 1, 0); | |
163 | ||
164 | return val ? __fls(val) : size; | |
165 | } | |
166 | ||
167 | return _find_last_bit(addr, size); | |
168 | } | |
169 | #endif | |
170 | ||
169c474f WBG |
171 | /** |
172 | * find_next_clump8 - find next 8-bit clump with set bits in a memory region | |
173 | * @clump: location to store copy of found clump | |
174 | * @addr: address to base the search on | |
175 | * @size: bitmap size in number of bits | |
176 | * @offset: bit offset at which to start searching | |
177 | * | |
178 | * Returns the bit offset for the next set clump; the found clump value is | |
179 | * copied to the location pointed by @clump. If no bits are set, returns @size. | |
180 | */ | |
181 | extern unsigned long find_next_clump8(unsigned long *clump, | |
182 | const unsigned long *addr, | |
183 | unsigned long size, unsigned long offset); | |
184 | ||
185 | #define find_first_clump8(clump, bits, size) \ | |
186 | find_next_clump8((clump), (bits), (size), 0) | |
187 | ||
c7f612cd | 188 | #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */ |