1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2023, 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_bitmap - 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