diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index c6dbd6115cc5..6e6ad0680829 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -300,12 +300,41 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr) } /* - * ATTENTION: - * find_first_bit_left() and find_next_bit_left() use MSB0 encoding. + * Functions which use MSB0 bit numbering. + * On an s390x system the bits are numbered: + * |0..............63|64............127|128...........191|192...........255| + * and on s390: + * |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255| */ -unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size); -unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, - unsigned long offset); +unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size); +unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, + unsigned long offset); + +static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr) +{ + return set_bit(nr ^ (BITS_PER_LONG - 1), ptr); +} + +static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr) +{ + return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr); +} + +static inline void __set_bit_inv(unsigned long nr, volatile unsigned long *ptr) +{ + return __set_bit(nr ^ (BITS_PER_LONG - 1), ptr); +} + +static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr) +{ + return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr); +} + +static inline int test_bit_inv(unsigned long nr, + const volatile unsigned long *ptr) +{ + return test_bit(nr ^ (BITS_PER_LONG - 1), ptr); +} #ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES diff --git a/arch/s390/lib/find.c b/arch/s390/lib/find.c index 8963929b06b9..620d34d6487e 100644 --- a/arch/s390/lib/find.c +++ b/arch/s390/lib/find.c @@ -15,7 +15,7 @@ #include #include -unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size) +unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size) { const unsigned long *p = addr; unsigned long result = 0; @@ -35,10 +35,10 @@ unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size) found: return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); } -EXPORT_SYMBOL(find_first_bit_left); +EXPORT_SYMBOL(find_first_bit_inv); -unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, - unsigned long offset) +unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, + unsigned long offset) { const unsigned long *p = addr + (offset / BITS_PER_LONG); unsigned long result = offset & ~(BITS_PER_LONG - 1); @@ -74,4 +74,4 @@ found_first: found_middle: return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); } -EXPORT_SYMBOL(find_next_bit_left); +EXPORT_SYMBOL(find_next_bit_inv); diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index d028fd800c9c..f055df0b167f 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -194,15 +194,14 @@ EXPORT_SYMBOL(airq_iv_release); */ unsigned long airq_iv_alloc_bit(struct airq_iv *iv) { - const unsigned long be_to_le = BITS_PER_LONG - 1; unsigned long bit; if (!iv->avail) return -1UL; spin_lock(&iv->lock); - bit = find_first_bit_left(iv->avail, iv->bits); + bit = find_first_bit_inv(iv->avail, iv->bits); if (bit < iv->bits) { - clear_bit(bit ^ be_to_le, iv->avail); + clear_bit_inv(bit, iv->avail); if (bit >= iv->end) iv->end = bit + 1; } else @@ -220,19 +219,17 @@ EXPORT_SYMBOL(airq_iv_alloc_bit); */ void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) { - const unsigned long be_to_le = BITS_PER_LONG - 1; - if (!iv->avail) return; spin_lock(&iv->lock); /* Clear (possibly left over) interrupt bit */ - clear_bit(bit ^ be_to_le, iv->vector); + clear_bit_inv(bit, iv->vector); /* Make the bit position available again */ - set_bit(bit ^ be_to_le, iv->avail); + set_bit_inv(bit, iv->avail); if (bit == iv->end - 1) { /* Find new end of bit-field */ while (--iv->end > 0) - if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail)) + if (!test_bit_inv(iv->end - 1, iv->avail)) break; } spin_unlock(&iv->lock); @@ -251,15 +248,13 @@ EXPORT_SYMBOL(airq_iv_free_bit); unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, unsigned long end) { - const unsigned long be_to_le = BITS_PER_LONG - 1; unsigned long bit; /* Find non-zero bit starting from 'ivs->next'. */ - bit = find_next_bit_left(iv->vector, end, start); + bit = find_next_bit_inv(iv->vector, end, start); if (bit >= end) return -1UL; - /* Clear interrupt bit (find left uses big-endian bit numbers) */ - clear_bit(bit ^ be_to_le, iv->vector); + clear_bit_inv(bit, iv->vector); return bit; } EXPORT_SYMBOL(airq_iv_scan);