diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index ea2c0e3b00743329555c833e4e8cf22afff4bdf4..10c782137d4636333a3d7728aae1b866e3eb475b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -189,6 +189,11 @@ EXPORT_SYMBOL(___test_and_change_bit); EXPORT_SYMBOL(___test_and_set_le_bit); EXPORT_SYMBOL(___test_and_clear_le_bit); +/* Bit searching */ +EXPORT_SYMBOL(find_next_bit); +EXPORT_SYMBOL(find_next_zero_bit); +EXPORT_SYMBOL(find_next_zero_le_bit); + EXPORT_SYMBOL(ivector_table); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index 14a4c728b13c160fb7d4c99976fc10bdd6245ceb..230e59f1888e5f3f2d388720178c0d22c8865aff 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile @@ -10,7 +10,8 @@ lib-y := PeeCeeI.o blockops.o strlen.o strncmp.o \ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ - U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o splock.o + U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o splock.o \ + find_bit.o lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c new file mode 100644 index 0000000000000000000000000000000000000000..420dfbafdfa4c01700478b20eaf6a3496fa854f4 --- /dev/null +++ b/arch/sparc64/lib/find_bit.c @@ -0,0 +1,125 @@ +#include <asm/bitops.h> + +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +unsigned long find_next_bit(unsigned long *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = addr + (offset >> 6); + unsigned long result = offset & ~63UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 63UL; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < 64) + goto found_first; + if (tmp) + goto found_middle; + size -= 64; + result += 64; + } + while (size & ~63UL) { + if ((tmp = *(p++))) + goto found_middle; + result += 64; + size -= 64; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (64 - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} + +/* find_next_zero_bit() finds the first zero bit in a bit string of length + * 'size' bits, starting the search at bit 'offset'. This is largely based + * on Linus's ALPHA routines, which are pretty portable BTW. + */ + +unsigned long find_next_zero_bit(unsigned long *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = addr + (offset >> 6); + unsigned long result = offset & ~63UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 63UL; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (64-offset); + if (size < 64) + goto found_first; + if (~tmp) + goto found_middle; + size -= 64; + result += 64; + } + while (size & ~63UL) { + if (~(tmp = *(p++))) + goto found_middle; + result += 64; + size -= 64; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} + +unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = addr + (offset >> 6); + unsigned long result = offset & ~63UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 63UL; + if(offset) { + tmp = __swab64p(p++); + tmp |= (~0UL >> (64-offset)); + if(size < 64) + goto found_first; + if(~tmp) + goto found_middle; + size -= 64; + result += 64; + } + while(size & ~63) { + if(~(tmp = __swab64p(p++))) + goto found_middle; + result += 64; + size -= 64; + } + if(!size) + return result; + tmp = __swab64p(p); +found_first: + tmp |= (~0UL << size); + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h index 9deee1ab71203af04c8a5a30c75378f2ee637d57..d32c138437c3ec537e0782afad8d8604ace5fad6 100644 --- a/include/asm-sparc64/bitops.h +++ b/include/asm-sparc64/bitops.h @@ -204,43 +204,7 @@ static __inline__ unsigned int hweight8(unsigned int w) * @offset: The bitnumber to start searching at * @size: The maximum size to search */ -static __inline__ unsigned long find_next_bit(unsigned long *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < 64) - goto found_first; - if (tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if ((tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (64 - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} +extern unsigned long find_next_bit(unsigned long *, unsigned long, unsigned long); /** * find_first_bit - find the first set bit in a memory region @@ -258,43 +222,7 @@ static __inline__ unsigned long find_next_bit(unsigned long *addr, unsigned long * on Linus's ALPHA routines, which are pretty portable BTW. */ -static __inline__ unsigned long find_next_zero_bit(unsigned long *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (64-offset); - if (size < 64) - goto found_first; - if (~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} +extern unsigned long find_next_zero_bit(unsigned long *, unsigned long, unsigned long); #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) @@ -320,42 +248,7 @@ static __inline__ int test_le_bit(int nr, __const__ unsigned long * addr) #define find_first_zero_le_bit(addr, size) \ find_next_zero_le_bit((addr), (size), 0) -static __inline__ unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if(offset) { - tmp = __swab64p(p++); - tmp |= (~0UL >> (64-offset)); - if(size < 64) - goto found_first; - if(~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while(size & ~63) { - if(~(tmp = __swab64p(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if(!size) - return result; - tmp = __swab64p(p); -found_first: - tmp |= (~0UL << size); - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} +extern unsigned long find_next_zero_le_bit(unsigned long *, unsigned long, unsigned long); #ifdef __KERNEL__