]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/drivers/net/ice/base/ice_bitops.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / ice / base / ice_bitops.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2019
3 */
4
5 #ifndef _ICE_BITOPS_H_
6 #define _ICE_BITOPS_H_
7
8 /* Define the size of the bitmap chunk */
9 typedef u32 ice_bitmap_t;
10
11
12 /* Number of bits per bitmap chunk */
13 #define BITS_PER_CHUNK (BITS_PER_BYTE * sizeof(ice_bitmap_t))
14 /* Determine which chunk a bit belongs in */
15 #define BIT_CHUNK(nr) ((nr) / BITS_PER_CHUNK)
16 /* How many chunks are required to store this many bits */
17 #define BITS_TO_CHUNKS(sz) DIVIDE_AND_ROUND_UP((sz), BITS_PER_CHUNK)
18 /* Which bit inside a chunk this bit corresponds to */
19 #define BIT_IN_CHUNK(nr) ((nr) % BITS_PER_CHUNK)
20 /* How many bits are valid in the last chunk, assumes nr > 0 */
21 #define LAST_CHUNK_BITS(nr) ((((nr) - 1) % BITS_PER_CHUNK) + 1)
22 /* Generate a bitmask of valid bits in the last chunk, assumes nr > 0 */
23 #define LAST_CHUNK_MASK(nr) (((ice_bitmap_t)~0) >> \
24 (BITS_PER_CHUNK - LAST_CHUNK_BITS(nr)))
25
26 #define ice_declare_bitmap(A, sz) \
27 ice_bitmap_t A[BITS_TO_CHUNKS(sz)]
28
29 static inline bool ice_is_bit_set_internal(u16 nr, const ice_bitmap_t *bitmap)
30 {
31 return !!(*bitmap & BIT(nr));
32 }
33
34 /*
35 * If atomic version of the bitops are required, each specific OS
36 * implementation will need to implement OS/platform specific atomic
37 * version of the functions below:
38 *
39 * ice_clear_bit_internal
40 * ice_set_bit_internal
41 * ice_test_and_clear_bit_internal
42 * ice_test_and_set_bit_internal
43 *
44 * and define macro ICE_ATOMIC_BITOPS to overwrite the default non-atomic
45 * implementation.
46 */
47 static inline void ice_clear_bit_internal(u16 nr, ice_bitmap_t *bitmap)
48 {
49 *bitmap &= ~BIT(nr);
50 }
51
52 static inline void ice_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
53 {
54 *bitmap |= BIT(nr);
55 }
56
57 static inline bool ice_test_and_clear_bit_internal(u16 nr,
58 ice_bitmap_t *bitmap)
59 {
60 if (ice_is_bit_set_internal(nr, bitmap)) {
61 ice_clear_bit_internal(nr, bitmap);
62 return true;
63 }
64 return false;
65 }
66
67 static inline bool ice_test_and_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
68 {
69 if (ice_is_bit_set_internal(nr, bitmap))
70 return true;
71
72 ice_set_bit_internal(nr, bitmap);
73 return false;
74 }
75
76 /**
77 * ice_is_bit_set - Check state of a bit in a bitmap
78 * @bitmap: the bitmap to check
79 * @nr: the bit to check
80 *
81 * Returns true if bit nr of bitmap is set. False otherwise. Assumes that nr
82 * is less than the size of the bitmap.
83 */
84 static inline bool ice_is_bit_set(const ice_bitmap_t *bitmap, u16 nr)
85 {
86 return ice_is_bit_set_internal(BIT_IN_CHUNK(nr),
87 &bitmap[BIT_CHUNK(nr)]);
88 }
89
90 /**
91 * ice_clear_bit - Clear a bit in a bitmap
92 * @bitmap: the bitmap to change
93 * @nr: the bit to change
94 *
95 * Clears the bit nr in bitmap. Assumes that nr is less than the size of the
96 * bitmap.
97 */
98 static inline void ice_clear_bit(u16 nr, ice_bitmap_t *bitmap)
99 {
100 ice_clear_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
101 }
102
103 /**
104 * ice_set_bit - Set a bit in a bitmap
105 * @bitmap: the bitmap to change
106 * @nr: the bit to change
107 *
108 * Sets the bit nr in bitmap. Assumes that nr is less than the size of the
109 * bitmap.
110 */
111 static inline void ice_set_bit(u16 nr, ice_bitmap_t *bitmap)
112 {
113 ice_set_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
114 }
115
116 /**
117 * ice_test_and_clear_bit - Atomically clear a bit and return the old bit value
118 * @nr: the bit to change
119 * @bitmap: the bitmap to change
120 *
121 * Check and clear the bit nr in bitmap. Assumes that nr is less than the size
122 * of the bitmap.
123 */
124 static inline bool
125 ice_test_and_clear_bit(u16 nr, ice_bitmap_t *bitmap)
126 {
127 return ice_test_and_clear_bit_internal(BIT_IN_CHUNK(nr),
128 &bitmap[BIT_CHUNK(nr)]);
129 }
130
131 /**
132 * ice_test_and_set_bit - Atomically set a bit and return the old bit value
133 * @nr: the bit to change
134 * @bitmap: the bitmap to change
135 *
136 * Check and set the bit nr in bitmap. Assumes that nr is less than the size of
137 * the bitmap.
138 */
139 static inline bool
140 ice_test_and_set_bit(u16 nr, ice_bitmap_t *bitmap)
141 {
142 return ice_test_and_set_bit_internal(BIT_IN_CHUNK(nr),
143 &bitmap[BIT_CHUNK(nr)]);
144 }
145
146 /* ice_zero_bitmap - set bits of bitmap to zero.
147 * @bmp: bitmap to set zeros
148 * @size: Size of the bitmaps in bits
149 *
150 * This function sets bits of a bitmap to zero.
151 */
152 static inline void ice_zero_bitmap(ice_bitmap_t *bmp, u16 size)
153 {
154 ice_bitmap_t mask;
155 u16 i;
156
157 /* Handle all but last chunk*/
158 for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
159 bmp[i] = 0;
160 /* For the last chunk, we want to take care of not to modify bits
161 * outside the size boundary. ~mask take care of all the bits outside
162 * the boundary.
163 */
164 mask = LAST_CHUNK_MASK(size);
165 bmp[i] &= ~mask;
166 }
167
168 /**
169 * ice_and_bitmap - bitwise AND 2 bitmaps and store result in dst bitmap
170 * @dst: Destination bitmap that receive the result of the operation
171 * @bmp1: The first bitmap to intersect
172 * @bmp2: The second bitmap to intersect wit the first
173 * @size: Size of the bitmaps in bits
174 *
175 * This function performs a bitwise AND on two "source" bitmaps of the same size
176 * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
177 * size as the "source" bitmaps to avoid buffer overflows. This function returns
178 * a non-zero value if at least one bit location from both "source" bitmaps is
179 * non-zero.
180 */
181 static inline int
182 ice_and_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
183 const ice_bitmap_t *bmp2, u16 size)
184 {
185 ice_bitmap_t res = 0, mask;
186 u16 i;
187
188 /* Handle all but the last chunk */
189 for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++) {
190 dst[i] = bmp1[i] & bmp2[i];
191 res |= dst[i];
192 }
193
194 /* We want to take care not to modify any bits outside of the bitmap
195 * size, even in the destination bitmap. Thus, we won't directly
196 * assign the last bitmap, but instead use a bitmask to ensure we only
197 * modify bits which are within the size, and leave any bits above the
198 * size value alone.
199 */
200 mask = LAST_CHUNK_MASK(size);
201 dst[i] &= ~mask;
202 dst[i] |= (bmp1[i] & bmp2[i]) & mask;
203 res |= dst[i] & mask;
204
205 return res != 0;
206 }
207
208 /**
209 * ice_or_bitmap - bitwise OR 2 bitmaps and store result in dst bitmap
210 * @dst: Destination bitmap that receive the result of the operation
211 * @bmp1: The first bitmap to intersect
212 * @bmp2: The second bitmap to intersect wit the first
213 * @size: Size of the bitmaps in bits
214 *
215 * This function performs a bitwise OR on two "source" bitmaps of the same size
216 * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
217 * size as the "source" bitmaps to avoid buffer overflows.
218 */
219 static inline void
220 ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
221 const ice_bitmap_t *bmp2, u16 size)
222 {
223 ice_bitmap_t mask;
224 u16 i;
225
226 /* Handle all but last chunk*/
227 for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
228 dst[i] = bmp1[i] | bmp2[i];
229
230 /* We want to only OR bits within the size. Furthermore, we also do
231 * not want to modify destination bits which are beyond the specified
232 * size. Use a bitmask to ensure that we only modify the bits that are
233 * within the specified size.
234 */
235 mask = LAST_CHUNK_MASK(size);
236 dst[i] &= ~mask;
237 dst[i] |= (bmp1[i] | bmp2[i]) & mask;
238 }
239
240 /**
241 * ice_find_next_bit - Find the index of the next set bit of a bitmap
242 * @bitmap: the bitmap to scan
243 * @size: the size in bits of the bitmap
244 * @offset: the offset to start at
245 *
246 * Scans the bitmap and returns the index of the first set bit which is equal
247 * to or after the specified offset. Will return size if no bits are set.
248 */
249 static inline u16
250 ice_find_next_bit(const ice_bitmap_t *bitmap, u16 size, u16 offset)
251 {
252 u16 i, j;
253
254 if (offset >= size)
255 return size;
256
257 /* Since the starting position may not be directly on a chunk
258 * boundary, we need to be careful to handle the first chunk specially
259 */
260 i = BIT_CHUNK(offset);
261 if (bitmap[i] != 0) {
262 u16 off = i * BITS_PER_CHUNK;
263
264 for (j = offset % BITS_PER_CHUNK; j < BITS_PER_CHUNK; j++) {
265 if (ice_is_bit_set(bitmap, off + j))
266 return min(size, (u16)(off + j));
267 }
268 }
269
270 /* Now we handle the remaining chunks, if any */
271 for (i++; i < BITS_TO_CHUNKS(size); i++) {
272 if (bitmap[i] != 0) {
273 u16 off = i * BITS_PER_CHUNK;
274
275 for (j = 0; j < BITS_PER_CHUNK; j++) {
276 if (ice_is_bit_set(bitmap, off + j))
277 return min(size, (u16)(off + j));
278 }
279 }
280 }
281 return size;
282 }
283
284 /**
285 * ice_find_first_bit - Find the index of the first set bit of a bitmap
286 * @bitmap: the bitmap to scan
287 * @size: the size in bits of the bitmap
288 *
289 * Scans the bitmap and returns the index of the first set bit. Will return
290 * size if no bits are set.
291 */
292 static inline u16 ice_find_first_bit(const ice_bitmap_t *bitmap, u16 size)
293 {
294 return ice_find_next_bit(bitmap, size, 0);
295 }
296
297 /**
298 * ice_is_any_bit_set - Return true of any bit in the bitmap is set
299 * @bitmap: the bitmap to check
300 * @size: the size of the bitmap
301 *
302 * Equivalent to checking if ice_find_first_bit returns a value less than the
303 * bitmap size.
304 */
305 static inline bool ice_is_any_bit_set(ice_bitmap_t *bitmap, u16 size)
306 {
307 return ice_find_first_bit(bitmap, size) < size;
308 }
309
310 /**
311 * ice_cp_bitmap - copy bitmaps.
312 * @dst: bitmap destination
313 * @src: bitmap to copy from
314 * @size: Size of the bitmaps in bits
315 *
316 * This function copy bitmap from src to dst.
317 */
318 static inline void ice_cp_bitmap(ice_bitmap_t *dst, ice_bitmap_t *src, u16 size)
319 {
320 ice_bitmap_t mask;
321 u16 i;
322
323 /* Handle all but last chunk*/
324 for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
325 dst[i] = src[i];
326
327 /* We want to only copy bits within the size.*/
328 mask = LAST_CHUNK_MASK(size);
329 dst[i] &= ~mask;
330 dst[i] |= src[i] & mask;
331 }
332
333 /**
334 * ice_cmp_bitmaps - compares two bitmaps.
335 * @bmp1: the bitmap to compare
336 * @bmp2: the bitmap to compare with bmp1
337 * @size: Size of the bitmaps in bits
338 *
339 * This function compares two bitmaps, and returns result as true or false.
340 */
341 static inline bool
342 ice_cmp_bitmap(ice_bitmap_t *bmp1, ice_bitmap_t *bmp2, u16 size)
343 {
344 ice_bitmap_t mask;
345 u16 i;
346
347 /* Handle all but last chunk*/
348 for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
349 if (bmp1[i] != bmp2[i])
350 return false;
351
352 /* We want to only compare bits within the size.*/
353 mask = LAST_CHUNK_MASK(size);
354 if ((bmp1[i] & mask) != (bmp2[i] & mask))
355 return false;
356
357 return true;
358 }
359
360
361 #endif /* _ICE_BITOPS_H_ */