
From: Lukas Funke lukas.funke@weidmueller.com
Add generic 'find_next_zero_bit()' implementation in order to enable the use of the 'for_each_set_bitrange' macro. The implementation is currently missing for the sandbox-arch and using the function results in a linker error. The implementation is copied from the 'arm' implementation.
Signed-off-by: Lukas Funke lukas.funke@weidmueller.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v3: - Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h - Redirect sandbox ffz() implementation to generic __ffs() impl
arch/sandbox/include/asm/bitops.h | 60 +++++++++++++++++++------------ 1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h index f27d5e98c5..6950916962 100644 --- a/arch/sandbox/include/asm/bitops.h +++ b/arch/sandbox/include/asm/bitops.h @@ -104,9 +104,6 @@ static inline int __test_and_change_bit(int nr, void *addr) return (old & mask) != 0; }
-extern int find_first_zero_bit(void *addr, unsigned size); -extern int find_next_zero_bit(void *addr, int size, int offset); - /* * This routine doesn't need to be atomic. */ @@ -119,27 +116,46 @@ static inline int test_bit(int nr, const void *addr) * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -static inline unsigned long ffz(unsigned long word) -{ - int k; - - word = ~word; - k = 31; - if (word & 0x0000ffff) { - k -= 16; word <<= 16; - } - if (word & 0x00ff0000) { - k -= 8; word <<= 8; - } - if (word & 0x0f000000) { - k -= 4; word <<= 4; +#define ffz(x) __ffs(~(x)) + +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + +static inline int find_next_zero_bit(const unsigned long *addr, int size, + int offset) { + unsigned long *p = ((unsigned long *)addr) + (offset / BITS_PER_LONG); + unsigned long result = offset & ~(BITS_PER_LONG - 1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= (BITS_PER_LONG - 1); + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; } - if (word & 0x30000000) { - k -= 2; word <<= 2; + while (size & ~(BITS_PER_LONG - 1)) { + tmp = *(p++); + if (~tmp) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; } - if (word & 0x40000000) - k -= 1; - return k; + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; +found_middle: + return result + ffz(tmp); }
/*