18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MSB0 numbered special bitops handling. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * The bits are numbered: 68c2ecf20Sopenharmony_ci * |0..............63|64............127|128...........191|192...........255| 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * The reason for this bit numbering is the fact that the hardware sets bits 98c2ecf20Sopenharmony_ci * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap 108c2ecf20Sopenharmony_ci * from the 'wrong end'. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/compiler.h> 148c2ecf20Sopenharmony_ci#include <linux/bitops.h> 158c2ecf20Sopenharmony_ci#include <linux/export.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciunsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci const unsigned long *p = addr; 208c2ecf20Sopenharmony_ci unsigned long result = 0; 218c2ecf20Sopenharmony_ci unsigned long tmp; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci while (size & ~(BITS_PER_LONG - 1)) { 248c2ecf20Sopenharmony_ci if ((tmp = *(p++))) 258c2ecf20Sopenharmony_ci goto found; 268c2ecf20Sopenharmony_ci result += BITS_PER_LONG; 278c2ecf20Sopenharmony_ci size -= BITS_PER_LONG; 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci if (!size) 308c2ecf20Sopenharmony_ci return result; 318c2ecf20Sopenharmony_ci tmp = (*p) & (~0UL << (BITS_PER_LONG - size)); 328c2ecf20Sopenharmony_ci if (!tmp) /* Are any bits set? */ 338c2ecf20Sopenharmony_ci return result + size; /* Nope. */ 348c2ecf20Sopenharmony_cifound: 358c2ecf20Sopenharmony_ci return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(find_first_bit_inv); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciunsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, 408c2ecf20Sopenharmony_ci unsigned long offset) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci const unsigned long *p = addr + (offset / BITS_PER_LONG); 438c2ecf20Sopenharmony_ci unsigned long result = offset & ~(BITS_PER_LONG - 1); 448c2ecf20Sopenharmony_ci unsigned long tmp; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (offset >= size) 478c2ecf20Sopenharmony_ci return size; 488c2ecf20Sopenharmony_ci size -= result; 498c2ecf20Sopenharmony_ci offset %= BITS_PER_LONG; 508c2ecf20Sopenharmony_ci if (offset) { 518c2ecf20Sopenharmony_ci tmp = *(p++); 528c2ecf20Sopenharmony_ci tmp &= (~0UL >> offset); 538c2ecf20Sopenharmony_ci if (size < BITS_PER_LONG) 548c2ecf20Sopenharmony_ci goto found_first; 558c2ecf20Sopenharmony_ci if (tmp) 568c2ecf20Sopenharmony_ci goto found_middle; 578c2ecf20Sopenharmony_ci size -= BITS_PER_LONG; 588c2ecf20Sopenharmony_ci result += BITS_PER_LONG; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci while (size & ~(BITS_PER_LONG-1)) { 618c2ecf20Sopenharmony_ci if ((tmp = *(p++))) 628c2ecf20Sopenharmony_ci goto found_middle; 638c2ecf20Sopenharmony_ci result += BITS_PER_LONG; 648c2ecf20Sopenharmony_ci size -= BITS_PER_LONG; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci if (!size) 678c2ecf20Sopenharmony_ci return result; 688c2ecf20Sopenharmony_ci tmp = *p; 698c2ecf20Sopenharmony_cifound_first: 708c2ecf20Sopenharmony_ci tmp &= (~0UL << (BITS_PER_LONG - size)); 718c2ecf20Sopenharmony_ci if (!tmp) /* Are any bits set? */ 728c2ecf20Sopenharmony_ci return result + size; /* Nope. */ 738c2ecf20Sopenharmony_cifound_middle: 748c2ecf20Sopenharmony_ci return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(find_next_bit_inv); 77