f0aa8ce8886ee274af674390c2dc8c3cd190ec14
[dpdk.git] / 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  * Set all of the bits in a bitmap to zero. Note that this function assumes it
151  * operates on an ice_bitmap_t which was declared using ice_declare_bitmap. It
152  * will zero every bit in the last chunk, even if those bits are beyond the
153  * size.
154  */
155 static inline void ice_zero_bitmap(ice_bitmap_t *bmp, u16 size)
156 {
157         ice_memset(bmp, 0, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
158                    ICE_NONDMA_MEM);
159 }
160
161 /**
162  * ice_and_bitmap - bitwise AND 2 bitmaps and store result in dst bitmap
163  * @dst: Destination bitmap that receive the result of the operation
164  * @bmp1: The first bitmap to intersect
165  * @bmp2: The second bitmap to intersect wit the first
166  * @size: Size of the bitmaps in bits
167  *
168  * This function performs a bitwise AND on two "source" bitmaps of the same size
169  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
170  * size as the "source" bitmaps to avoid buffer overflows. This function returns
171  * a non-zero value if at least one bit location from both "source" bitmaps is
172  * non-zero.
173  */
174 static inline int
175 ice_and_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
176                const ice_bitmap_t *bmp2, u16 size)
177 {
178         ice_bitmap_t res = 0, mask;
179         u16 i;
180
181         /* Handle all but the last chunk */
182         for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++) {
183                 dst[i] = bmp1[i] & bmp2[i];
184                 res |= dst[i];
185         }
186
187         /* We want to take care not to modify any bits outside of the bitmap
188          * size, even in the destination bitmap. Thus, we won't directly
189          * assign the last bitmap, but instead use a bitmask to ensure we only
190          * modify bits which are within the size, and leave any bits above the
191          * size value alone.
192          */
193         mask = LAST_CHUNK_MASK(size);
194         dst[i] = (dst[i] & ~mask) | ((bmp1[i] & bmp2[i]) & mask);
195         res |= dst[i] & mask;
196
197         return res != 0;
198 }
199
200 /**
201  * ice_or_bitmap - bitwise OR 2 bitmaps and store result in dst bitmap
202  * @dst: Destination bitmap that receive the result of the operation
203  * @bmp1: The first bitmap to intersect
204  * @bmp2: The second bitmap to intersect wit the first
205  * @size: Size of the bitmaps in bits
206  *
207  * This function performs a bitwise OR on two "source" bitmaps of the same size
208  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
209  * size as the "source" bitmaps to avoid buffer overflows.
210  */
211 static inline void
212 ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
213               const ice_bitmap_t *bmp2, u16 size)
214 {
215         ice_bitmap_t mask;
216         u16 i;
217
218         /* Handle all but last chunk*/
219         for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
220                 dst[i] = bmp1[i] | bmp2[i];
221
222         /* We want to only OR bits within the size. Furthermore, we also do
223          * not want to modify destination bits which are beyond the specified
224          * size. Use a bitmask to ensure that we only modify the bits that are
225          * within the specified size.
226          */
227         mask = LAST_CHUNK_MASK(size);
228         dst[i] = (dst[i] & ~mask) | ((bmp1[i] | bmp2[i]) & mask);
229 }
230
231 /**
232  * ice_xor_bitmap - bitwise XOR 2 bitmaps and store result in dst bitmap
233  * @dst: Destination bitmap that receive the result of the operation
234  * @bmp1: The first bitmap of XOR operation
235  * @bmp2: The second bitmap to XOR with the first
236  * @size: Size of the bitmaps in bits
237  *
238  * This function performs a bitwise XOR on two "source" bitmaps of the same size
239  * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
240  * size as the "source" bitmaps to avoid buffer overflows.
241  */
242 static inline void
243 ice_xor_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
244                const ice_bitmap_t *bmp2, u16 size)
245 {
246         ice_bitmap_t mask;
247         u16 i;
248
249         /* Handle all but last chunk*/
250         for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
251                 dst[i] = bmp1[i] ^ bmp2[i];
252
253         /* We want to only XOR bits within the size. Furthermore, we also do
254          * not want to modify destination bits which are beyond the specified
255          * size. Use a bitmask to ensure that we only modify the bits that are
256          * within the specified size.
257          */
258         mask = LAST_CHUNK_MASK(size);
259         dst[i] = (dst[i] & ~mask) | ((bmp1[i] ^ bmp2[i]) & mask);
260 }
261
262 /**
263  * ice_find_next_bit - Find the index of the next set bit of a bitmap
264  * @bitmap: the bitmap to scan
265  * @size: the size in bits of the bitmap
266  * @offset: the offset to start at
267  *
268  * Scans the bitmap and returns the index of the first set bit which is equal
269  * to or after the specified offset. Will return size if no bits are set.
270  */
271 static inline u16
272 ice_find_next_bit(const ice_bitmap_t *bitmap, u16 size, u16 offset)
273 {
274         u16 i, j;
275
276         if (offset >= size)
277                 return size;
278
279         /* Since the starting position may not be directly on a chunk
280          * boundary, we need to be careful to handle the first chunk specially
281          */
282         i = BIT_CHUNK(offset);
283         if (bitmap[i] != 0) {
284                 u16 off = i * BITS_PER_CHUNK;
285
286                 for (j = offset % BITS_PER_CHUNK; j < BITS_PER_CHUNK; j++) {
287                         if (ice_is_bit_set(bitmap, off + j))
288                                 return min(size, (u16)(off + j));
289                 }
290         }
291
292         /* Now we handle the remaining chunks, if any */
293         for (i++; i < BITS_TO_CHUNKS(size); i++) {
294                 if (bitmap[i] != 0) {
295                         u16 off = i * BITS_PER_CHUNK;
296
297                         for (j = 0; j < BITS_PER_CHUNK; j++) {
298                                 if (ice_is_bit_set(bitmap, off + j))
299                                         return min(size, (u16)(off + j));
300                         }
301                 }
302         }
303         return size;
304 }
305
306 /**
307  * ice_find_first_bit - Find the index of the first set bit of a bitmap
308  * @bitmap: the bitmap to scan
309  * @size: the size in bits of the bitmap
310  *
311  * Scans the bitmap and returns the index of the first set bit. Will return
312  * size if no bits are set.
313  */
314 static inline u16 ice_find_first_bit(const ice_bitmap_t *bitmap, u16 size)
315 {
316         return ice_find_next_bit(bitmap, size, 0);
317 }
318
319 /**
320  * ice_is_any_bit_set - Return true of any bit in the bitmap is set
321  * @bitmap: the bitmap to check
322  * @size: the size of the bitmap
323  *
324  * Equivalent to checking if ice_find_first_bit returns a value less than the
325  * bitmap size.
326  */
327 static inline bool ice_is_any_bit_set(ice_bitmap_t *bitmap, u16 size)
328 {
329         return ice_find_first_bit(bitmap, size) < size;
330 }
331
332 /**
333  * ice_cp_bitmap - copy bitmaps.
334  * @dst: bitmap destination
335  * @src: bitmap to copy from
336  * @size: Size of the bitmaps in bits
337  *
338  * This function copy bitmap from src to dst. Note that this function assumes
339  * it is operating on a bitmap declared using ice_declare_bitmap. It will copy
340  * the entire last chunk even if this contains bits beyond the size.
341  */
342 static inline void ice_cp_bitmap(ice_bitmap_t *dst, ice_bitmap_t *src, u16 size)
343 {
344         ice_memcpy(dst, src, BITS_TO_CHUNKS(size) * sizeof(ice_bitmap_t),
345                    ICE_NONDMA_TO_NONDMA);
346 }
347
348 /**
349  * ice_cmp_bitmaps - compares two bitmaps.
350  * @bmp1: the bitmap to compare
351  * @bmp2: the bitmap to compare with bmp1
352  * @size: Size of the bitmaps in bits
353  *
354  * This function compares two bitmaps, and returns result as true or false.
355  */
356 static inline bool
357 ice_cmp_bitmap(ice_bitmap_t *bmp1, ice_bitmap_t *bmp2, u16 size)
358 {
359         ice_bitmap_t mask;
360         u16 i;
361
362         /* Handle all but last chunk*/
363         for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
364                 if (bmp1[i] != bmp2[i])
365                         return false;
366
367         /* We want to only compare bits within the size.*/
368         mask = LAST_CHUNK_MASK(size);
369         if ((bmp1[i] & mask) != (bmp2[i] & mask))
370                 return false;
371
372         return true;
373 }
374
375
376 #endif /* _ICE_BITOPS_H_ */