xref: /f-stack/dpdk/drivers/net/ice/base/ice_bitops.h (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2020 Intel Corporation
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 /* Number of bits per bitmap chunk */
12 #define BITS_PER_CHUNK		(BITS_PER_BYTE * sizeof(ice_bitmap_t))
13 /* Determine which chunk a bit belongs in */
14 #define BIT_CHUNK(nr)		((nr) / BITS_PER_CHUNK)
15 /* How many chunks are required to store this many bits */
16 #define BITS_TO_CHUNKS(sz)	DIVIDE_AND_ROUND_UP((sz), BITS_PER_CHUNK)
17 /* Which bit inside a chunk this bit corresponds to */
18 #define BIT_IN_CHUNK(nr)	((nr) % BITS_PER_CHUNK)
19 /* How many bits are valid in the last chunk, assumes nr > 0 */
20 #define LAST_CHUNK_BITS(nr)	((((nr) - 1) % BITS_PER_CHUNK) + 1)
21 /* Generate a bitmask of valid bits in the last chunk, assumes nr > 0 */
22 #define LAST_CHUNK_MASK(nr)	(((ice_bitmap_t)~0) >> \
23 				 (BITS_PER_CHUNK - LAST_CHUNK_BITS(nr)))
24 
25 #define ice_declare_bitmap(A, sz) \
26 	ice_bitmap_t A[BITS_TO_CHUNKS(sz)]
27 
ice_is_bit_set_internal(u16 nr,const ice_bitmap_t * bitmap)28 static inline bool ice_is_bit_set_internal(u16 nr, const ice_bitmap_t *bitmap)
29 {
30 	return !!(*bitmap & BIT(nr));
31 }
32 
33 /*
34  * If atomic version of the bitops are required, each specific OS
35  * implementation will need to implement OS/platform specific atomic
36  * version of the functions below:
37  *
38  * ice_clear_bit_internal
39  * ice_set_bit_internal
40  * ice_test_and_clear_bit_internal
41  * ice_test_and_set_bit_internal
42  *
43  * and define macro ICE_ATOMIC_BITOPS to overwrite the default non-atomic
44  * implementation.
45  */
ice_clear_bit_internal(u16 nr,ice_bitmap_t * bitmap)46 static inline void ice_clear_bit_internal(u16 nr, ice_bitmap_t *bitmap)
47 {
48 	*bitmap &= ~BIT(nr);
49 }
50 
ice_set_bit_internal(u16 nr,ice_bitmap_t * bitmap)51 static inline void ice_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
52 {
53 	*bitmap |= BIT(nr);
54 }
55 
ice_test_and_clear_bit_internal(u16 nr,ice_bitmap_t * bitmap)56 static inline bool ice_test_and_clear_bit_internal(u16 nr,
57 						   ice_bitmap_t *bitmap)
58 {
59 	if (ice_is_bit_set_internal(nr, bitmap)) {
60 		ice_clear_bit_internal(nr, bitmap);
61 		return true;
62 	}
63 	return false;
64 }
65 
ice_test_and_set_bit_internal(u16 nr,ice_bitmap_t * bitmap)66 static inline bool ice_test_and_set_bit_internal(u16 nr, ice_bitmap_t *bitmap)
67 {
68 	if (ice_is_bit_set_internal(nr, bitmap))
69 		return true;
70 
71 	ice_set_bit_internal(nr, bitmap);
72 	return false;
73 }
74 
75 /**
76  * ice_is_bit_set - Check state of a bit in a bitmap
77  * @bitmap: the bitmap to check
78  * @nr: the bit to check
79  *
80  * Returns true if bit nr of bitmap is set. False otherwise. Assumes that nr
81  * is less than the size of the bitmap.
82  */
ice_is_bit_set(const ice_bitmap_t * bitmap,u16 nr)83 static inline bool ice_is_bit_set(const ice_bitmap_t *bitmap, u16 nr)
84 {
85 	return ice_is_bit_set_internal(BIT_IN_CHUNK(nr),
86 				       &bitmap[BIT_CHUNK(nr)]);
87 }
88 
89 /**
90  * ice_clear_bit - Clear a bit in a bitmap
91  * @bitmap: the bitmap to change
92  * @nr: the bit to change
93  *
94  * Clears the bit nr in bitmap. Assumes that nr is less than the size of the
95  * bitmap.
96  */
ice_clear_bit(u16 nr,ice_bitmap_t * bitmap)97 static inline void ice_clear_bit(u16 nr, ice_bitmap_t *bitmap)
98 {
99 	ice_clear_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
100 }
101 
102 /**
103  * ice_set_bit - Set a bit in a bitmap
104  * @bitmap: the bitmap to change
105  * @nr: the bit to change
106  *
107  * Sets the bit nr in bitmap. Assumes that nr is less than the size of the
108  * bitmap.
109  */
ice_set_bit(u16 nr,ice_bitmap_t * bitmap)110 static inline void ice_set_bit(u16 nr, ice_bitmap_t *bitmap)
111 {
112 	ice_set_bit_internal(BIT_IN_CHUNK(nr), &bitmap[BIT_CHUNK(nr)]);
113 }
114 
115 /**
116  * ice_test_and_clear_bit - Atomically clear a bit and return the old bit value
117  * @nr: the bit to change
118  * @bitmap: the bitmap to change
119  *
120  * Check and clear the bit nr in bitmap. Assumes that nr is less than the size
121  * of the bitmap.
122  */
123 static inline bool
ice_test_and_clear_bit(u16 nr,ice_bitmap_t * bitmap)124 ice_test_and_clear_bit(u16 nr, ice_bitmap_t *bitmap)
125 {
126 	return ice_test_and_clear_bit_internal(BIT_IN_CHUNK(nr),
127 					       &bitmap[BIT_CHUNK(nr)]);
128 }
129 
130 /**
131  * ice_test_and_set_bit - Atomically set a bit and return the old bit value
132  * @nr: the bit to change
133  * @bitmap: the bitmap to change
134  *
135  * Check and set the bit nr in bitmap. Assumes that nr is less than the size of
136  * the bitmap.
137  */
138 static inline bool
ice_test_and_set_bit(u16 nr,ice_bitmap_t * bitmap)139 ice_test_and_set_bit(u16 nr, ice_bitmap_t *bitmap)
140 {
141 	return ice_test_and_set_bit_internal(BIT_IN_CHUNK(nr),
142 					     &bitmap[BIT_CHUNK(nr)]);
143 }
144 
145 /* ice_zero_bitmap - set bits of bitmap to zero.
146  * @bmp: bitmap to set zeros
147  * @size: Size of the bitmaps in bits
148  *
149  * Set all of the bits in a bitmap to zero. Note that this function assumes it
150  * operates on an ice_bitmap_t which was declared using ice_declare_bitmap. It
151  * will zero every bit in the last chunk, even if those bits are beyond the
152  * size.
153  */
ice_zero_bitmap(ice_bitmap_t * bmp,u16 size)154 static inline void ice_zero_bitmap(ice_bitmap_t *bmp, u16 size)
155 {
156 	ice_memset(bmp, 0, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
157 		   ICE_NONDMA_MEM);
158 }
159 
160 /**
161  * ice_and_bitmap - bitwise AND 2 bitmaps and store result in dst bitmap
162  * @dst: Destination bitmap that receive the result of the operation
163  * @bmp1: The first bitmap to intersect
164  * @bmp2: The second bitmap to intersect wit the first
165  * @size: Size of the bitmaps in bits
166  *
167  * This function performs a bitwise AND on two "source" bitmaps of the same size
168  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
169  * size as the "source" bitmaps to avoid buffer overflows. This function returns
170  * a non-zero value if at least one bit location from both "source" bitmaps is
171  * non-zero.
172  */
173 static inline int
ice_and_bitmap(ice_bitmap_t * dst,const ice_bitmap_t * bmp1,const ice_bitmap_t * bmp2,u16 size)174 ice_and_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
175 	       const ice_bitmap_t *bmp2, u16 size)
176 {
177 	ice_bitmap_t res = 0, mask;
178 	u16 i;
179 
180 	/* Handle all but the last chunk */
181 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++) {
182 		dst[i] = bmp1[i] & bmp2[i];
183 		res |= dst[i];
184 	}
185 
186 	/* We want to take care not to modify any bits outside of the bitmap
187 	 * size, even in the destination bitmap. Thus, we won't directly
188 	 * assign the last bitmap, but instead use a bitmask to ensure we only
189 	 * modify bits which are within the size, and leave any bits above the
190 	 * size value alone.
191 	 */
192 	mask = LAST_CHUNK_MASK(size);
193 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] & bmp2[i]) & mask);
194 	res |= dst[i] & mask;
195 
196 	return res != 0;
197 }
198 
199 /**
200  * ice_or_bitmap - bitwise OR 2 bitmaps and store result in dst bitmap
201  * @dst: Destination bitmap that receive the result of the operation
202  * @bmp1: The first bitmap to intersect
203  * @bmp2: The second bitmap to intersect wit the first
204  * @size: Size of the bitmaps in bits
205  *
206  * This function performs a bitwise OR on two "source" bitmaps of the same size
207  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
208  * size as the "source" bitmaps to avoid buffer overflows.
209  */
210 static inline void
ice_or_bitmap(ice_bitmap_t * dst,const ice_bitmap_t * bmp1,const ice_bitmap_t * bmp2,u16 size)211 ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
212 	      const ice_bitmap_t *bmp2, u16 size)
213 {
214 	ice_bitmap_t mask;
215 	u16 i;
216 
217 	/* Handle all but last chunk */
218 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
219 		dst[i] = bmp1[i] | bmp2[i];
220 
221 	/* We want to only OR bits within the size. Furthermore, we also do
222 	 * not want to modify destination bits which are beyond the specified
223 	 * size. Use a bitmask to ensure that we only modify the bits that are
224 	 * within the specified size.
225 	 */
226 	mask = LAST_CHUNK_MASK(size);
227 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] | bmp2[i]) & mask);
228 }
229 
230 /**
231  * ice_xor_bitmap - bitwise XOR 2 bitmaps and store result in dst bitmap
232  * @dst: Destination bitmap that receive the result of the operation
233  * @bmp1: The first bitmap of XOR operation
234  * @bmp2: The second bitmap to XOR with the first
235  * @size: Size of the bitmaps in bits
236  *
237  * This function performs a bitwise XOR on two "source" bitmaps of the same size
238  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
239  * size as the "source" bitmaps to avoid buffer overflows.
240  */
241 static inline void
ice_xor_bitmap(ice_bitmap_t * dst,const ice_bitmap_t * bmp1,const ice_bitmap_t * bmp2,u16 size)242 ice_xor_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
243 	       const ice_bitmap_t *bmp2, u16 size)
244 {
245 	ice_bitmap_t mask;
246 	u16 i;
247 
248 	/* Handle all but last chunk */
249 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
250 		dst[i] = bmp1[i] ^ bmp2[i];
251 
252 	/* We want to only XOR bits within the size. Furthermore, we also do
253 	 * not want to modify destination bits which are beyond the specified
254 	 * size. Use a bitmask to ensure that we only modify the bits that are
255 	 * within the specified size.
256 	 */
257 	mask = LAST_CHUNK_MASK(size);
258 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] ^ bmp2[i]) & mask);
259 }
260 
261 /**
262  * ice_andnot_bitmap - bitwise ANDNOT 2 bitmaps and result in dst bitmap
263  * @dst: Destination bitmap that receive the result of the operation
264  * @bmp1: The first bitmap of ANDNOT operation
265  * @bmp2: The second bitmap to ANDNOT operation
266  * @size: Size of the bitmaps in bits
267  *
268  * This function performs a bitwise ANDNOT on two "source" bitmaps of the same
269  * size, and stores the result to "dst" bitmap. The "dst" bitmap must be of the
270  * same size as the "source" bitmaps to avoid buffer overflows.
271  */
272 static inline void
ice_andnot_bitmap(ice_bitmap_t * dst,const ice_bitmap_t * bmp1,const ice_bitmap_t * bmp2,u16 size)273 ice_andnot_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
274 		  const ice_bitmap_t *bmp2, u16 size)
275 {
276 	ice_bitmap_t mask;
277 	u16 i;
278 
279 	/* Handle all but last chunk */
280 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
281 		dst[i] = bmp1[i] & ~bmp2[i];
282 
283 	/* We want to only clear bits within the size. Furthermore, we also do
284 	 * not want to modify destination bits which are beyond the specified
285 	 * size. Use a bitmask to ensure that we only modify the bits that are
286 	 * within the specified size.
287 	 */
288 	mask = LAST_CHUNK_MASK(size);
289 	dst[i] = (dst[i] & ~mask) | ((bmp1[i] & ~bmp2[i]) & mask);
290 }
291 
292 /**
293  * ice_find_next_bit - Find the index of the next set bit of a bitmap
294  * @bitmap: the bitmap to scan
295  * @size: the size in bits of the bitmap
296  * @offset: the offset to start at
297  *
298  * Scans the bitmap and returns the index of the first set bit which is equal
299  * to or after the specified offset. Will return size if no bits are set.
300  */
301 static inline u16
ice_find_next_bit(const ice_bitmap_t * bitmap,u16 size,u16 offset)302 ice_find_next_bit(const ice_bitmap_t *bitmap, u16 size, u16 offset)
303 {
304 	u16 i, j;
305 
306 	if (offset >= size)
307 		return size;
308 
309 	/* Since the starting position may not be directly on a chunk
310 	 * boundary, we need to be careful to handle the first chunk specially
311 	 */
312 	i = BIT_CHUNK(offset);
313 	if (bitmap[i] != 0) {
314 		u16 off = i * BITS_PER_CHUNK;
315 
316 		for (j = offset % BITS_PER_CHUNK; j < BITS_PER_CHUNK; j++) {
317 			if (ice_is_bit_set(bitmap, off + j))
318 				return min(size, (u16)(off + j));
319 		}
320 	}
321 
322 	/* Now we handle the remaining chunks, if any */
323 	for (i++; i < BITS_TO_CHUNKS(size); i++) {
324 		if (bitmap[i] != 0) {
325 			u16 off = i * BITS_PER_CHUNK;
326 
327 			for (j = 0; j < BITS_PER_CHUNK; j++) {
328 				if (ice_is_bit_set(bitmap, off + j))
329 					return min(size, (u16)(off + j));
330 			}
331 		}
332 	}
333 	return size;
334 }
335 
336 /**
337  * ice_find_first_bit - Find the index of the first set bit of a bitmap
338  * @bitmap: the bitmap to scan
339  * @size: the size in bits of the bitmap
340  *
341  * Scans the bitmap and returns the index of the first set bit. Will return
342  * size if no bits are set.
343  */
ice_find_first_bit(const ice_bitmap_t * bitmap,u16 size)344 static inline u16 ice_find_first_bit(const ice_bitmap_t *bitmap, u16 size)
345 {
346 	return ice_find_next_bit(bitmap, size, 0);
347 }
348 
349 #define ice_for_each_set_bit(_bitpos, _addr, _maxlen)	\
350 	for ((_bitpos) = ice_find_first_bit((_addr), (_maxlen)); \
351 	     (_bitpos) < (_maxlen); \
352 	     (_bitpos) = ice_find_next_bit((_addr), (_maxlen), (_bitpos) + 1))
353 
354 /**
355  * ice_is_any_bit_set - Return true of any bit in the bitmap is set
356  * @bitmap: the bitmap to check
357  * @size: the size of the bitmap
358  *
359  * Equivalent to checking if ice_find_first_bit returns a value less than the
360  * bitmap size.
361  */
ice_is_any_bit_set(ice_bitmap_t * bitmap,u16 size)362 static inline bool ice_is_any_bit_set(ice_bitmap_t *bitmap, u16 size)
363 {
364 	return ice_find_first_bit(bitmap, size) < size;
365 }
366 
367 /**
368  * ice_cp_bitmap - copy bitmaps.
369  * @dst: bitmap destination
370  * @src: bitmap to copy from
371  * @size: Size of the bitmaps in bits
372  *
373  * This function copy bitmap from src to dst. Note that this function assumes
374  * it is operating on a bitmap declared using ice_declare_bitmap. It will copy
375  * the entire last chunk even if this contains bits beyond the size.
376  */
ice_cp_bitmap(ice_bitmap_t * dst,ice_bitmap_t * src,u16 size)377 static inline void ice_cp_bitmap(ice_bitmap_t *dst, ice_bitmap_t *src, u16 size)
378 {
379 	ice_memcpy(dst, src, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
380 		   ICE_NONDMA_TO_NONDMA);
381 }
382 
383 /**
384  * ice_bitmap_set - set a number of bits in bitmap from a starting position
385  * @dst: bitmap destination
386  * @pos: first bit position to set
387  * @num_bits: number of bits to set
388  *
389  * This function sets bits in a bitmap from pos to (pos + num_bits) - 1.
390  * Note that this function assumes it is operating on a bitmap declared using
391  * ice_declare_bitmap.
392  */
393 static inline void
ice_bitmap_set(ice_bitmap_t * dst,u16 pos,u16 num_bits)394 ice_bitmap_set(ice_bitmap_t *dst, u16 pos, u16 num_bits)
395 {
396 	u16 i;
397 
398 	for (i = pos; i < pos + num_bits; i++)
399 		ice_set_bit(i, dst);
400 }
401 
402 /**
403  * ice_bitmap_hweight - hamming weight of bitmap
404  * @bm: bitmap pointer
405  * @size: size of bitmap (in bits)
406  *
407  * This function determines the number of set bits in a bitmap.
408  * Note that this function assumes it is operating on a bitmap declared using
409  * ice_declare_bitmap.
410  */
411 static inline int
ice_bitmap_hweight(ice_bitmap_t * bm,u16 size)412 ice_bitmap_hweight(ice_bitmap_t *bm, u16 size)
413 {
414 	int count = 0;
415 	u16 bit = 0;
416 
417 	while (size > (bit = ice_find_next_bit(bm, size, bit))) {
418 		count++;
419 		bit++;
420 	}
421 
422 	return count;
423 }
424 
425 /**
426  * ice_cmp_bitmaps - compares two bitmaps.
427  * @bmp1: the bitmap to compare
428  * @bmp2: the bitmap to compare with bmp1
429  * @size: Size of the bitmaps in bits
430  *
431  * This function compares two bitmaps, and returns result as true or false.
432  */
433 static inline bool
ice_cmp_bitmap(ice_bitmap_t * bmp1,ice_bitmap_t * bmp2,u16 size)434 ice_cmp_bitmap(ice_bitmap_t *bmp1, ice_bitmap_t *bmp2, u16 size)
435 {
436 	ice_bitmap_t mask;
437 	u16 i;
438 
439 	/* Handle all but last chunk */
440 	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
441 		if (bmp1[i] != bmp2[i])
442 			return false;
443 
444 	/* We want to only compare bits within the size */
445 	mask = LAST_CHUNK_MASK(size);
446 	if ((bmp1[i] & mask) != (bmp2[i] & mask))
447 		return false;
448 
449 	return true;
450 }
451 
452 #endif /* _ICE_BITOPS_H_ */
453