1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2746479cdSHeiko Carstens /* 3746479cdSHeiko Carstens * MSB0 numbered special bitops handling. 4746479cdSHeiko Carstens * 548002bd5SHeiko Carstens * The bits are numbered: 6746479cdSHeiko Carstens * |0..............63|64............127|128...........191|192...........255| 7746479cdSHeiko Carstens * 8746479cdSHeiko Carstens * The reason for this bit numbering is the fact that the hardware sets bits 9746479cdSHeiko Carstens * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap 10746479cdSHeiko Carstens * from the 'wrong end'. 11746479cdSHeiko Carstens */ 12746479cdSHeiko Carstens 13746479cdSHeiko Carstens #include <linux/compiler.h> 14746479cdSHeiko Carstens #include <linux/bitops.h> 15746479cdSHeiko Carstens #include <linux/export.h> 16746479cdSHeiko Carstens find_first_bit_inv(const unsigned long * addr,unsigned long size)177d7c7b24SHeiko Carstensunsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size) 18746479cdSHeiko Carstens { 19746479cdSHeiko Carstens const unsigned long *p = addr; 20746479cdSHeiko Carstens unsigned long result = 0; 21746479cdSHeiko Carstens unsigned long tmp; 22746479cdSHeiko Carstens 23746479cdSHeiko Carstens while (size & ~(BITS_PER_LONG - 1)) { 24746479cdSHeiko Carstens if ((tmp = *(p++))) 25746479cdSHeiko Carstens goto found; 26746479cdSHeiko Carstens result += BITS_PER_LONG; 27746479cdSHeiko Carstens size -= BITS_PER_LONG; 28746479cdSHeiko Carstens } 29746479cdSHeiko Carstens if (!size) 30746479cdSHeiko Carstens return result; 31746479cdSHeiko Carstens tmp = (*p) & (~0UL << (BITS_PER_LONG - size)); 32746479cdSHeiko Carstens if (!tmp) /* Are any bits set? */ 33746479cdSHeiko Carstens return result + size; /* Nope. */ 34746479cdSHeiko Carstens found: 35746479cdSHeiko Carstens return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 36746479cdSHeiko Carstens } 377d7c7b24SHeiko Carstens EXPORT_SYMBOL(find_first_bit_inv); 38746479cdSHeiko Carstens find_next_bit_inv(const unsigned long * addr,unsigned long size,unsigned long offset)397d7c7b24SHeiko Carstensunsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, 40746479cdSHeiko Carstens unsigned long offset) 41746479cdSHeiko Carstens { 42746479cdSHeiko Carstens const unsigned long *p = addr + (offset / BITS_PER_LONG); 43746479cdSHeiko Carstens unsigned long result = offset & ~(BITS_PER_LONG - 1); 44746479cdSHeiko Carstens unsigned long tmp; 45746479cdSHeiko Carstens 46746479cdSHeiko Carstens if (offset >= size) 47746479cdSHeiko Carstens return size; 48746479cdSHeiko Carstens size -= result; 49746479cdSHeiko Carstens offset %= BITS_PER_LONG; 50746479cdSHeiko Carstens if (offset) { 51746479cdSHeiko Carstens tmp = *(p++); 52746479cdSHeiko Carstens tmp &= (~0UL >> offset); 53746479cdSHeiko Carstens if (size < BITS_PER_LONG) 54746479cdSHeiko Carstens goto found_first; 55746479cdSHeiko Carstens if (tmp) 56746479cdSHeiko Carstens goto found_middle; 57746479cdSHeiko Carstens size -= BITS_PER_LONG; 58746479cdSHeiko Carstens result += BITS_PER_LONG; 59746479cdSHeiko Carstens } 60746479cdSHeiko Carstens while (size & ~(BITS_PER_LONG-1)) { 61746479cdSHeiko Carstens if ((tmp = *(p++))) 62746479cdSHeiko Carstens goto found_middle; 63746479cdSHeiko Carstens result += BITS_PER_LONG; 64746479cdSHeiko Carstens size -= BITS_PER_LONG; 65746479cdSHeiko Carstens } 66746479cdSHeiko Carstens if (!size) 67746479cdSHeiko Carstens return result; 68746479cdSHeiko Carstens tmp = *p; 69746479cdSHeiko Carstens found_first: 70746479cdSHeiko Carstens tmp &= (~0UL << (BITS_PER_LONG - size)); 71746479cdSHeiko Carstens if (!tmp) /* Are any bits set? */ 72746479cdSHeiko Carstens return result + size; /* Nope. */ 73746479cdSHeiko Carstens found_middle: 74746479cdSHeiko Carstens return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 75746479cdSHeiko Carstens } 767d7c7b24SHeiko Carstens EXPORT_SYMBOL(find_next_bit_inv); 77