|  | // SPDX-License-Identifier: GPL-2.0-only | 
|  | /* | 
|  | * From lib/bitmap.c | 
|  | * Helper functions for bitmap.h. | 
|  | */ | 
|  | #include <linux/bitmap.h> | 
|  |  | 
|  | unsigned int __bitmap_weight(const unsigned long *bitmap, int bits) | 
|  | { | 
|  | unsigned int k, w = 0, lim = bits/BITS_PER_LONG; | 
|  |  | 
|  | for (k = 0; k < lim; k++) | 
|  | w += hweight_long(bitmap[k]); | 
|  |  | 
|  | if (bits % BITS_PER_LONG) | 
|  | w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); | 
|  |  | 
|  | return w; | 
|  | } | 
|  |  | 
|  | void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, | 
|  | const unsigned long *bitmap2, int bits) | 
|  | { | 
|  | int k; | 
|  | int nr = BITS_TO_LONGS(bits); | 
|  |  | 
|  | for (k = 0; k < nr; k++) | 
|  | dst[k] = bitmap1[k] | bitmap2[k]; | 
|  | } | 
|  |  | 
|  | size_t bitmap_scnprintf(unsigned long *bitmap, unsigned int nbits, | 
|  | char *buf, size_t size) | 
|  | { | 
|  | /* current bit is 'cur', most recently seen range is [rbot, rtop] */ | 
|  | unsigned int cur, rbot, rtop; | 
|  | bool first = true; | 
|  | size_t ret = 0; | 
|  |  | 
|  | rbot = cur = find_first_bit(bitmap, nbits); | 
|  | while (cur < nbits) { | 
|  | rtop = cur; | 
|  | cur = find_next_bit(bitmap, nbits, cur + 1); | 
|  | if (cur < nbits && cur <= rtop + 1) | 
|  | continue; | 
|  |  | 
|  | if (!first) | 
|  | ret += scnprintf(buf + ret, size - ret, ","); | 
|  |  | 
|  | first = false; | 
|  |  | 
|  | ret += scnprintf(buf + ret, size - ret, "%d", rbot); | 
|  | if (rbot < rtop) | 
|  | ret += scnprintf(buf + ret, size - ret, "-%d", rtop); | 
|  |  | 
|  | rbot = cur; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | bool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, | 
|  | const unsigned long *bitmap2, unsigned int bits) | 
|  | { | 
|  | unsigned int k; | 
|  | unsigned int lim = bits/BITS_PER_LONG; | 
|  | unsigned long result = 0; | 
|  |  | 
|  | for (k = 0; k < lim; k++) | 
|  | result |= (dst[k] = bitmap1[k] & bitmap2[k]); | 
|  | if (bits % BITS_PER_LONG) | 
|  | result |= (dst[k] = bitmap1[k] & bitmap2[k] & | 
|  | BITMAP_LAST_WORD_MASK(bits)); | 
|  | return result != 0; | 
|  | } | 
|  |  | 
|  | bool __bitmap_equal(const unsigned long *bitmap1, | 
|  | const unsigned long *bitmap2, unsigned int bits) | 
|  | { | 
|  | unsigned int k, lim = bits/BITS_PER_LONG; | 
|  | for (k = 0; k < lim; ++k) | 
|  | if (bitmap1[k] != bitmap2[k]) | 
|  | return false; | 
|  |  | 
|  | if (bits % BITS_PER_LONG) | 
|  | if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) | 
|  | return false; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool __bitmap_intersects(const unsigned long *bitmap1, | 
|  | const unsigned long *bitmap2, unsigned int bits) | 
|  | { | 
|  | unsigned int k, lim = bits/BITS_PER_LONG; | 
|  | for (k = 0; k < lim; ++k) | 
|  | if (bitmap1[k] & bitmap2[k]) | 
|  | return true; | 
|  |  | 
|  | if (bits % BITS_PER_LONG) | 
|  | if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void __bitmap_set(unsigned long *map, unsigned int start, int len) | 
|  | { | 
|  | unsigned long *p = map + BIT_WORD(start); | 
|  | const unsigned int size = start + len; | 
|  | int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); | 
|  | unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); | 
|  |  | 
|  | while (len - bits_to_set >= 0) { | 
|  | *p |= mask_to_set; | 
|  | len -= bits_to_set; | 
|  | bits_to_set = BITS_PER_LONG; | 
|  | mask_to_set = ~0UL; | 
|  | p++; | 
|  | } | 
|  | if (len) { | 
|  | mask_to_set &= BITMAP_LAST_WORD_MASK(size); | 
|  | *p |= mask_to_set; | 
|  | } | 
|  | } | 
|  |  | 
|  | void __bitmap_clear(unsigned long *map, unsigned int start, int len) | 
|  | { | 
|  | unsigned long *p = map + BIT_WORD(start); | 
|  | const unsigned int size = start + len; | 
|  | int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); | 
|  | unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); | 
|  |  | 
|  | while (len - bits_to_clear >= 0) { | 
|  | *p &= ~mask_to_clear; | 
|  | len -= bits_to_clear; | 
|  | bits_to_clear = BITS_PER_LONG; | 
|  | mask_to_clear = ~0UL; | 
|  | p++; | 
|  | } | 
|  | if (len) { | 
|  | mask_to_clear &= BITMAP_LAST_WORD_MASK(size); | 
|  | *p &= ~mask_to_clear; | 
|  | } | 
|  | } |