summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorYury Norov <ynorov@nvidia.com>2025-12-22 14:11:37 -0500
committerYury Norov <ynorov@nvidia.com>2026-03-23 13:33:51 -0400
commitbf31ddc14f8c6bcd4987c31fe2bc9e93e433b41a (patch)
treed346d3e6372cd063d9d28b745381be13a206badf /include/linux
parent6c88ba561cfc2c5f35067519f46310059a9dc39a (diff)
bitmap: add bitmap_weight_from()
The function calculates a Hamming weight of a bitmap starting from an arbitrary bit. Signed-off-by: Yury Norov <ynorov@nvidia.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bitmap.h33
1 files changed, 33 insertions, 0 deletions
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index b0395e4ccf90..9c0d1de44350 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -57,6 +57,7 @@ struct device;
* bitmap_weight(src, nbits) Hamming Weight: number set bits
* bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap
* bitmap_weight_andnot(src1, src2, nbits) Hamming Weight of andnot'ed bitmap
+ * bitmap_weight_from(src, start, end) Hamming Weight starting from @start
* bitmap_set(dst, pos, nbits) Set specified bit area
* bitmap_clear(dst, pos, nbits) Clear specified bit area
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
@@ -479,6 +480,38 @@ unsigned long bitmap_weight_andnot(const unsigned long *src1,
return __bitmap_weight_andnot(src1, src2, nbits);
}
+/**
+ * bitmap_weight_from - Hamming weight for a memory region
+ * @bitmap: The base address
+ * @start: The bitnumber to starts weighting
+ * @end: the bitmap size in bits
+ *
+ * Returns the number of set bits in the region. If @start >= @end,
+ * return >= end.
+ */
+static __always_inline
+unsigned long bitmap_weight_from(const unsigned long *bitmap,
+ unsigned int start, unsigned int end)
+{
+ unsigned long w;
+
+ if (unlikely(start >= end))
+ return end;
+
+ if (small_const_nbits(end))
+ return hweight_long(*bitmap & GENMASK(end - 1, start));
+
+ bitmap += start / BITS_PER_LONG;
+ /* Opencode round_down() to not include math.h */
+ end -= start & ~(BITS_PER_LONG - 1);
+ start %= BITS_PER_LONG;
+ w = bitmap_weight(bitmap, end);
+ if (start)
+ w -= hweight_long(*bitmap & BITMAP_LAST_WORD_MASK(start));
+
+ return w;
+}
+
static __always_inline
void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits)
{