xref: /freebsd/sys/dev/ice/ice_bitops.h (revision 4d3fc8b0570b29fb0d6ee9525f104d52176ff0d4)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2022, Intel Corporation
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above copyright notice,
9  *      this list of conditions and the following disclaimer.
10  *
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *
15  *   3. Neither the name of the Intel Corporation nor the names of its
16  *      contributors may be used to endorse or promote products derived from
17  *      this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *  POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*$FreeBSD$*/
32 
33 #ifndef _ICE_BITOPS_H_
34 #define _ICE_BITOPS_H_
35 
36 #include "ice_defs.h"
37 #include "ice_osdep.h"
38 
39 /* Define the size of the bitmap chunk */
40 typedef u32 ice_bitmap_t;
41 
42 /* NOTE!
43  * Do not use any of the functions declared in this file
44  * on memory that was not declared with ice_declare_bitmap.
45  * Not following this rule might cause issues like split
46  * locks.
47  */
48 
49 /* Number of bits per bitmap chunk */
50 #define BITS_PER_CHUNK		(BITS_PER_BYTE * sizeof(ice_bitmap_t))
51 /* Determine which chunk a bit belongs in */
52 #define BIT_CHUNK(nr)		((nr) / BITS_PER_CHUNK)
53 /* How many chunks are required to store this many bits */
54 #define BITS_TO_CHUNKS(sz)	(((sz) + BITS_PER_CHUNK - 1) / BITS_PER_CHUNK)
55 /* Which bit inside a chunk this bit corresponds to */
56 #define BIT_IN_CHUNK(nr)	((nr) % BITS_PER_CHUNK)
57 /* How many bits are valid in the last chunk, assumes nr > 0 */
58 #define LAST_CHUNK_BITS(nr)	((((nr) - 1) % BITS_PER_CHUNK) + 1)
59 /* Generate a bitmask of valid bits in the last chunk, assumes nr > 0 */
60 #define LAST_CHUNK_MASK(nr)	(((ice_bitmap_t)~0) >> \
61 				 (BITS_PER_CHUNK - LAST_CHUNK_BITS(nr)))
62 
63 #define ice_declare_bitmap(A, sz) \
64 	ice_bitmap_t A[BITS_TO_CHUNKS(sz)]
65 
66 static inline bool ice_is_bit_set_internal(u16 nr, const ice_bitmap_t *bitmap)
67 {
68 	return !!(*bitmap & BIT(nr));
69 }
70 
71 /*
72  * If atomic version of the bitops are required, each specific OS
73  * implementation will need to implement OS/platform specific atomic
74  * version of the functions below:
75  *
76  * ice_clear_bit_internal
77  * ice_set_bit_internal
78  * ice_test_and_clear_bit_internal
79  * ice_test_and_set_bit_internal
80  *
81  * and define macro ICE_ATOMIC_BITOPS to overwrite the default non-atomic
82  * implementation.
83  */
84 static inline void ice_clear_bit_internal(u16 nr, ice_bitmap_t *bitmap)
85 {
86 	*bitmap &= ~BIT(nr);
87 }
88 
89 static inline void ice_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
90 {
91 	*bitmap |= BIT(nr);
92 }
93 
94 static inline bool ice_test_and_clear_bit_internal(u16 nr,
95 						   ice_bitmap_t *bitmap)
96 {
97 	if (ice_is_bit_set_internal(nr, bitmap)) {
98 		ice_clear_bit_internal(nr, bitmap);
99 		return true;
100 	}
101 	return false;
102 }
103 
104 static inline bool ice_test_and_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
105 {
106 	if (ice_is_bit_set_internal(nr, bitmap))
107 		return true;
108 
109 	ice_set_bit_internal(nr, bitmap);
110 	return false;
111 }
112 
113 /**
114  * ice_is_bit_set - Check state of a bit in a bitmap
115  * @bitmap: the bitmap to check
116  * @nr: the bit to check
117  *
118  * Returns true if bit nr of bitmap is set. False otherwise. Assumes that nr
119  * is less than the size of the bitmap.
120  */
121 static inline bool ice_is_bit_set(const ice_bitmap_t *bitmap, u16 nr)
122 {
123 	return ice_is_bit_set_internal(BIT_IN_CHUNK(nr),
124 				       &bitmap[BIT_CHUNK(nr)]);
125 }
126 
127 /**
128  * ice_clear_bit - Clear a bit in a bitmap
129  * @bitmap: the bitmap to change
130  * @nr: the bit to change
131  *
132  * Clears the bit nr in bitmap. Assumes that nr is less than the size of the
133  * bitmap.
134  */
135 static inline void ice_clear_bit(u16 nr, ice_bitmap_t *bitmap)
136 {
137 	ice_clear_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
138 }
139 
140 /**
141  * ice_set_bit - Set a bit in a bitmap
142  * @bitmap: the bitmap to change
143  * @nr: the bit to change
144  *
145  * Sets the bit nr in bitmap. Assumes that nr is less than the size of the
146  * bitmap.
147  */
148 static inline void ice_set_bit(u16 nr, ice_bitmap_t *bitmap)
149 {
150 	ice_set_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
151 }
152 
153 /**
154  * ice_test_and_clear_bit - Atomically clear a bit and return the old bit value
155  * @nr: the bit to change
156  * @bitmap: the bitmap to change
157  *
158  * Check and clear the bit nr in bitmap. Assumes that nr is less than the size
159  * of the bitmap.
160  */
161 static inline bool
162 ice_test_and_clear_bit(u16 nr, ice_bitmap_t *bitmap)
163 {
164 	return ice_test_and_clear_bit_internal(BIT_IN_CHUNK(nr),
165 					       &bitmap[BIT_CHUNK(nr)]);
166 }
167 
168 /**
169  * ice_test_and_set_bit - Atomically set a bit and return the old bit value
170  * @nr: the bit to change
171  * @bitmap: the bitmap to change
172  *
173  * Check and set the bit nr in bitmap. Assumes that nr is less than the size of
174  * the bitmap.
175  */
176 static inline bool
177 ice_test_and_set_bit(u16 nr, ice_bitmap_t *bitmap)
178 {
179 	return ice_test_and_set_bit_internal(BIT_IN_CHUNK(nr),
180 					     &bitmap[BIT_CHUNK(nr)]);
181 }
182 
183 /* ice_zero_bitmap - set bits of bitmap to zero.
184  * @bmp: bitmap to set zeros
185  * @size: Size of the bitmaps in bits
186  *
187  * Set all of the bits in a bitmap to zero. Note that this function assumes it
188  * operates on an ice_bitmap_t which was declared using ice_declare_bitmap. It
189  * will zero every bit in the last chunk, even if those bits are beyond the
190  * size.
191  */
192 static inline void ice_zero_bitmap(ice_bitmap_t *bmp, u16 size)
193 {
194 	ice_memset(bmp, 0, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
195 		   ICE_NONDMA_MEM);
196 }
197 
198 /**
199  * ice_and_bitmap - bitwise AND 2 bitmaps and store result in dst bitmap
200  * @dst: Destination bitmap that receive the result of the operation
201  * @bmp1: The first bitmap to intersect
202  * @bmp2: The second bitmap to intersect wit the first
203  * @size: Size of the bitmaps in bits
204  *
205  * This function performs a bitwise AND on two "source" bitmaps of the same size
206  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
207  * size as the "source" bitmaps to avoid buffer overflows. This function returns
208  * a non-zero value if at least one bit location from both "source" bitmaps is
209  * non-zero.
210  */
211 static inline int
212 ice_and_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
213 	       const ice_bitmap_t *bmp2, u16 size)
214 {
215 	ice_bitmap_t res = 0, mask;
216 	u16 i;
217 
218 	/* Handle all but the last chunk */
219 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++) {
220 		dst[i] = bmp1[i] & bmp2[i];
221 		res |= dst[i];
222 	}
223 
224 	/* We want to take care not to modify any bits outside of the bitmap
225 	 * size, even in the destination bitmap. Thus, we won't directly
226 	 * assign the last bitmap, but instead use a bitmask to ensure we only
227 	 * modify bits which are within the size, and leave any bits above the
228 	 * size value alone.
229 	 */
230 	mask = LAST_CHUNK_MASK(size);
231 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] & bmp2[i]) & mask);
232 	res |= dst[i] & mask;
233 
234 	return res != 0;
235 }
236 
237 /**
238  * ice_or_bitmap - bitwise OR 2 bitmaps and store result in dst bitmap
239  * @dst: Destination bitmap that receive the result of the operation
240  * @bmp1: The first bitmap to intersect
241  * @bmp2: The second bitmap to intersect wit the first
242  * @size: Size of the bitmaps in bits
243  *
244  * This function performs a bitwise OR on two "source" bitmaps of the same size
245  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
246  * size as the "source" bitmaps to avoid buffer overflows.
247  */
248 static inline void
249 ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
250 	      const ice_bitmap_t *bmp2, u16 size)
251 {
252 	ice_bitmap_t mask;
253 	u16 i;
254 
255 	/* Handle all but last chunk */
256 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
257 		dst[i] = bmp1[i] | bmp2[i];
258 
259 	/* We want to only OR bits within the size. Furthermore, we also do
260 	 * not want to modify destination bits which are beyond the specified
261 	 * size. Use a bitmask to ensure that we only modify the bits that are
262 	 * within the specified size.
263 	 */
264 	mask = LAST_CHUNK_MASK(size);
265 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] | bmp2[i]) & mask);
266 }
267 
268 /**
269  * ice_xor_bitmap - bitwise XOR 2 bitmaps and store result in dst bitmap
270  * @dst: Destination bitmap that receive the result of the operation
271  * @bmp1: The first bitmap of XOR operation
272  * @bmp2: The second bitmap to XOR with the first
273  * @size: Size of the bitmaps in bits
274  *
275  * This function performs a bitwise XOR on two "source" bitmaps of the same size
276  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
277  * size as the "source" bitmaps to avoid buffer overflows.
278  */
279 static inline void
280 ice_xor_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
281 	       const ice_bitmap_t *bmp2, u16 size)
282 {
283 	ice_bitmap_t mask;
284 	u16 i;
285 
286 	/* Handle all but last chunk */
287 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
288 		dst[i] = bmp1[i] ^ bmp2[i];
289 
290 	/* We want to only XOR bits within the size. Furthermore, we also do
291 	 * not want to modify destination bits which are beyond the specified
292 	 * size. Use a bitmask to ensure that we only modify the bits that are
293 	 * within the specified size.
294 	 */
295 	mask = LAST_CHUNK_MASK(size);
296 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] ^ bmp2[i]) & mask);
297 }
298 
299 /**
300  * ice_andnot_bitmap - bitwise ANDNOT 2 bitmaps and result in dst bitmap
301  * @dst: Destination bitmap that receive the result of the operation
302  * @bmp1: The first bitmap of ANDNOT operation
303  * @bmp2: The second bitmap to ANDNOT operation
304  * @size: Size of the bitmaps in bits
305  *
306  * This function performs a bitwise ANDNOT on two "source" bitmaps of the same
307  * size, and stores the result to "dst" bitmap. The "dst" bitmap must be of the
308  * same size as the "source" bitmaps to avoid buffer overflows.
309  */
310 static inline void
311 ice_andnot_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
312 		  const ice_bitmap_t *bmp2, u16 size)
313 {
314 	ice_bitmap_t mask;
315 	u16 i;
316 
317 	/* Handle all but last chunk */
318 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
319 		dst[i] = bmp1[i] & ~bmp2[i];
320 
321 	/* We want to only clear bits within the size. Furthermore, we also do
322 	 * not want to modify destination bits which are beyond the specified
323 	 * size. Use a bitmask to ensure that we only modify the bits that are
324 	 * within the specified size.
325 	 */
326 	mask = LAST_CHUNK_MASK(size);
327 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] & ~bmp2[i]) & mask);
328 }
329 
330 /**
331  * ice_find_next_bit - Find the index of the next set bit of a bitmap
332  * @bitmap: the bitmap to scan
333  * @size: the size in bits of the bitmap
334  * @offset: the offset to start at
335  *
336  * Scans the bitmap and returns the index of the first set bit which is equal
337  * to or after the specified offset. Will return size if no bits are set.
338  */
339 static inline u16
340 ice_find_next_bit(const ice_bitmap_t *bitmap, u16 size, u16 offset)
341 {
342 	u16 i, j;
343 
344 	if (offset >= size)
345 		return size;
346 
347 	/* Since the starting position may not be directly on a chunk
348 	 * boundary, we need to be careful to handle the first chunk specially
349 	 */
350 	i = BIT_CHUNK(offset);
351 	if (bitmap[i] != 0) {
352 		u16 off = i * BITS_PER_CHUNK;
353 
354 		for (j = offset % BITS_PER_CHUNK; j < BITS_PER_CHUNK; j++) {
355 			if (ice_is_bit_set(bitmap, off + j))
356 				return min(size, (u16)(off + j));
357 		}
358 	}
359 
360 	/* Now we handle the remaining chunks, if any */
361 	for (i++; i < BITS_TO_CHUNKS(size); i++) {
362 		if (bitmap[i] != 0) {
363 			u16 off = i * BITS_PER_CHUNK;
364 
365 			for (j = 0; j < BITS_PER_CHUNK; j++) {
366 				if (ice_is_bit_set(bitmap, off + j))
367 					return min(size, (u16)(off + j));
368 			}
369 		}
370 	}
371 	return size;
372 }
373 
374 /**
375  * ice_find_first_bit - Find the index of the first set bit of a bitmap
376  * @bitmap: the bitmap to scan
377  * @size: the size in bits of the bitmap
378  *
379  * Scans the bitmap and returns the index of the first set bit. Will return
380  * size if no bits are set.
381  */
382 static inline u16 ice_find_first_bit(const ice_bitmap_t *bitmap, u16 size)
383 {
384 	return ice_find_next_bit(bitmap, size, 0);
385 }
386 
387 #define ice_for_each_set_bit(_bitpos, _addr, _maxlen)	\
388 	for ((_bitpos) = ice_find_first_bit((_addr), (_maxlen)); \
389 	     (_bitpos) < (_maxlen); \
390 	     (_bitpos) = ice_find_next_bit((_addr), (_maxlen), (_bitpos) + 1))
391 
392 /**
393  * ice_is_any_bit_set - Return true of any bit in the bitmap is set
394  * @bitmap: the bitmap to check
395  * @size: the size of the bitmap
396  *
397  * Equivalent to checking if ice_find_first_bit returns a value less than the
398  * bitmap size.
399  */
400 static inline bool ice_is_any_bit_set(ice_bitmap_t *bitmap, u16 size)
401 {
402 	return ice_find_first_bit(bitmap, size) < size;
403 }
404 
405 /**
406  * ice_cp_bitmap - copy bitmaps.
407  * @dst: bitmap destination
408  * @src: bitmap to copy from
409  * @size: Size of the bitmaps in bits
410  *
411  * This function copy bitmap from src to dst. Note that this function assumes
412  * it is operating on a bitmap declared using ice_declare_bitmap. It will copy
413  * the entire last chunk even if this contains bits beyond the size.
414  */
415 static inline void ice_cp_bitmap(ice_bitmap_t *dst, ice_bitmap_t *src, u16 size)
416 {
417 	ice_memcpy(dst, src, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
418 		   ICE_NONDMA_TO_NONDMA);
419 }
420 
421 /**
422  * ice_bitmap_set - set a number of bits in bitmap from a starting position
423  * @dst: bitmap destination
424  * @pos: first bit position to set
425  * @num_bits: number of bits to set
426  *
427  * This function sets bits in a bitmap from pos to (pos + num_bits) - 1.
428  * Note that this function assumes it is operating on a bitmap declared using
429  * ice_declare_bitmap.
430  */
431 static inline void
432 ice_bitmap_set(ice_bitmap_t *dst, u16 pos, u16 num_bits)
433 {
434 	u16 i;
435 
436 	for (i = pos; i < pos + num_bits; i++)
437 		ice_set_bit(i, dst);
438 }
439 
440 /**
441  * ice_bitmap_hweight - hamming weight of bitmap
442  * @bm: bitmap pointer
443  * @size: size of bitmap (in bits)
444  *
445  * This function determines the number of set bits in a bitmap.
446  * Note that this function assumes it is operating on a bitmap declared using
447  * ice_declare_bitmap.
448  */
449 static inline int
450 ice_bitmap_hweight(ice_bitmap_t *bm, u16 size)
451 {
452 	int count = 0;
453 	u16 bit = 0;
454 
455 	while (size > (bit = ice_find_next_bit(bm, size, bit))) {
456 		count++;
457 		bit++;
458 	}
459 
460 	return count;
461 }
462 
463 /**
464  * ice_cmp_bitmaps - compares two bitmaps.
465  * @bmp1: the bitmap to compare
466  * @bmp2: the bitmap to compare with bmp1
467  * @size: Size of the bitmaps in bits
468  *
469  * This function compares two bitmaps, and returns result as true or false.
470  */
471 static inline bool
472 ice_cmp_bitmap(ice_bitmap_t *bmp1, ice_bitmap_t *bmp2, u16 size)
473 {
474 	ice_bitmap_t mask;
475 	u16 i;
476 
477 	/* Handle all but last chunk */
478 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
479 		if (bmp1[i] != bmp2[i])
480 			return false;
481 
482 	/* We want to only compare bits within the size */
483 	mask = LAST_CHUNK_MASK(size);
484 	if ((bmp1[i] & mask) != (bmp2[i] & mask))
485 		return false;
486 
487 	return true;
488 }
489 
490 /**
491  * ice_bitmap_from_array32 - copies u32 array source into bitmap destination
492  * @dst: the destination bitmap
493  * @src: the source u32 array
494  * @size: size of the bitmap (in bits)
495  *
496  * This function copies the src bitmap stored in an u32 array into the dst
497  * bitmap stored as an ice_bitmap_t.
498  */
499 static inline void
500 ice_bitmap_from_array32(ice_bitmap_t *dst, u32 *src, u16 size)
501 {
502 	u32 remaining_bits, i;
503 
504 #define BITS_PER_U32	(sizeof(u32) * BITS_PER_BYTE)
505 	/* clear bitmap so we only have to set when iterating */
506 	ice_zero_bitmap(dst, size);
507 
508 	for (i = 0; i < (u32)(size / BITS_PER_U32); i++) {
509 		u32 bit_offset = i * BITS_PER_U32;
510 		u32 entry = src[i];
511 		u32 j;
512 
513 		for (j = 0; j < BITS_PER_U32; j++) {
514 			if (entry & BIT(j))
515 				ice_set_bit((u16)(j + bit_offset), dst);
516 		}
517 	}
518 
519 	/* still need to check the leftover bits (i.e. if size isn't evenly
520 	 * divisible by BITS_PER_U32
521 	 **/
522 	remaining_bits = size % BITS_PER_U32;
523 	if (remaining_bits) {
524 		u32 bit_offset = i * BITS_PER_U32;
525 		u32 entry = src[i];
526 		u32 j;
527 
528 		for (j = 0; j < remaining_bits; j++) {
529 			if (entry & BIT(j))
530 				ice_set_bit((u16)(j + bit_offset), dst);
531 		}
532 	}
533 }
534 
535 #undef BIT_CHUNK
536 #undef BIT_IN_CHUNK
537 #undef LAST_CHUNK_BITS
538 #undef LAST_CHUNK_MASK
539 
540 #endif /* _ICE_BITOPS_H_ */
541