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_ */ 362