Inspired find_next_*_bit and find_last_bit, add find_last_zero_bit And add le support about find_last_bit and find_last_zero_bit. Signed-off-by: Levi Yun <ppbuk5246@xxxxxxxxx> --- lib/find_bit.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/lib/find_bit.c b/lib/find_bit.c index 4a8751010d59..f9dda2bf7fa9 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -90,7 +90,7 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, EXPORT_SYMBOL(find_next_zero_bit); #endif -#if !defined(find_next_and_bit) +#ifndef find_next_and_bit unsigned long find_next_and_bit(const unsigned long *addr1, const unsigned long *addr2, unsigned long size, unsigned long offset) @@ -141,7 +141,7 @@ unsigned long find_last_bit(const unsigned long *addr, unsigned long size) { if (size) { unsigned long val = BITMAP_LAST_WORD_MASK(size); - unsigned long idx = (size-1) / BITS_PER_LONG; + unsigned long idx = (size - 1) / BITS_PER_LONG; do { val &= addr[idx]; @@ -156,6 +156,27 @@ unsigned long find_last_bit(const unsigned long *addr, unsigned long size) EXPORT_SYMBOL(find_last_bit); #endif +#ifndef find_last_zero_bit +unsigned long find_last_zero_bit(const unsigned long *addr, unsigned long size) +{ + if (size) { + unsigned long val = BITMAP_LAST_WORD_MASK(size); + unsigned long idx = (size - 1) / BITS_PER_LONG; + + do { + val &= ~addr[idx]; + if (val) + return idx * BITS_PER_LONG + __fls(val); + + val = ~0ul; + } while (idx--); + } + + return size; +} +EXPORT_SYMBOL(find_last_zero_bit); +#endif + #ifdef __BIG_ENDIAN #ifndef find_next_zero_bit_le @@ -176,6 +197,45 @@ unsigned long find_next_bit_le(const void *addr, unsigned EXPORT_SYMBOL(find_next_bit_le); #endif +static unsigned long _find_last_bit_le(const unsigned long *addr, + unsigned long size, unsigned long invert) +{ + if (size) { + unsigned long val = BITMAP_LAST_WORD_MASK(size); + unsigned long tmp; + unsigned long idx = (size - 1) / BITS_PER_LONG; + + val = swab(val); + + do { + tmp = swab(addr[idx]); + tmp ^= invert; + val &= tmp; + if (val) + return idx * BITS_PER_LONG + __fls(val); + + val = ~0ul; + } while (idx--); + } + return size; +} + +#ifndef find_last_zero_bit_le +unsigned long find_last_zero_bit_le(const unsigned void *addr, unsigned long size) +{ + return _find_last_bit_le(addr, size, ~0UL); +} +EXPORT_SYMBOL(find_last_zero_bit_le); +#endif + +#ifdef find_last_bit_le +unsigned long find_last_bit_le(const unsigned void *addr, unsigned long size) +{ + return _find_last_bit_le(addr, size, 0UL); +} +EXPORT_SYMBOL(find_last_bit_le); +#endif + #endif /* __BIG_ENDIAN */ unsigned long find_next_clump8(unsigned long *clump, const unsigned long *addr, -- 2.27.0