aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/bitops.h39
-rw-r--r--arch/s390/lib/find.c10
-rw-r--r--drivers/s390/cio/airq.c19
3 files changed, 46 insertions, 22 deletions
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)
300} 300}
301 301
302/* 302/*
303 * ATTENTION: 303 * Functions which use MSB0 bit numbering.
304 * find_first_bit_left() and find_next_bit_left() use MSB0 encoding. 304 * On an s390x system the bits are numbered:
305 * |0..............63|64............127|128...........191|192...........255|
306 * and on s390:
307 * |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
305 */ 308 */
306unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size); 309unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size);
307unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, 310unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
308 unsigned long offset); 311 unsigned long offset);
312
313static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
314{
315 return set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
316}
317
318static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
319{
320 return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
321}
322
323static inline void __set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
324{
325 return __set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
326}
327
328static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
329{
330 return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
331}
332
333static inline int test_bit_inv(unsigned long nr,
334 const volatile unsigned long *ptr)
335{
336 return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
337}
309 338
310#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES 339#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
311 340
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 @@
15#include <linux/bitops.h> 15#include <linux/bitops.h>
16#include <linux/export.h> 16#include <linux/export.h>
17 17
18unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size) 18unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
19{ 19{
20 const unsigned long *p = addr; 20 const unsigned long *p = addr;
21 unsigned long result = 0; 21 unsigned long result = 0;
@@ -35,10 +35,10 @@ unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size)
35found: 35found:
36 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 36 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
37} 37}
38EXPORT_SYMBOL(find_first_bit_left); 38EXPORT_SYMBOL(find_first_bit_inv);
39 39
40unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, 40unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
41 unsigned long offset) 41 unsigned long offset)
42{ 42{
43 const unsigned long *p = addr + (offset / BITS_PER_LONG); 43 const unsigned long *p = addr + (offset / BITS_PER_LONG);
44 unsigned long result = offset & ~(BITS_PER_LONG - 1); 44 unsigned long result = offset & ~(BITS_PER_LONG - 1);
@@ -74,4 +74,4 @@ found_first:
74found_middle: 74found_middle:
75 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); 75 return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
76} 76}
77EXPORT_SYMBOL(find_next_bit_left); 77EXPORT_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);
194 */ 194 */
195unsigned long airq_iv_alloc_bit(struct airq_iv *iv) 195unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
196{ 196{
197 const unsigned long be_to_le = BITS_PER_LONG - 1;
198 unsigned long bit; 197 unsigned long bit;
199 198
200 if (!iv->avail) 199 if (!iv->avail)
201 return -1UL; 200 return -1UL;
202 spin_lock(&iv->lock); 201 spin_lock(&iv->lock);
203 bit = find_first_bit_left(iv->avail, iv->bits); 202 bit = find_first_bit_inv(iv->avail, iv->bits);
204 if (bit < iv->bits) { 203 if (bit < iv->bits) {
205 clear_bit(bit ^ be_to_le, iv->avail); 204 clear_bit_inv(bit, iv->avail);
206 if (bit >= iv->end) 205 if (bit >= iv->end)
207 iv->end = bit + 1; 206 iv->end = bit + 1;
208 } else 207 } else
@@ -220,19 +219,17 @@ EXPORT_SYMBOL(airq_iv_alloc_bit);
220 */ 219 */
221void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) 220void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
222{ 221{
223 const unsigned long be_to_le = BITS_PER_LONG - 1;
224
225 if (!iv->avail) 222 if (!iv->avail)
226 return; 223 return;
227 spin_lock(&iv->lock); 224 spin_lock(&iv->lock);
228 /* Clear (possibly left over) interrupt bit */ 225 /* Clear (possibly left over) interrupt bit */
229 clear_bit(bit ^ be_to_le, iv->vector); 226 clear_bit_inv(bit, iv->vector);
230 /* Make the bit position available again */ 227 /* Make the bit position available again */
231 set_bit(bit ^ be_to_le, iv->avail); 228 set_bit_inv(bit, iv->avail);
232 if (bit == iv->end - 1) { 229 if (bit == iv->end - 1) {
233 /* Find new end of bit-field */ 230 /* Find new end of bit-field */
234 while (--iv->end > 0) 231 while (--iv->end > 0)
235 if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail)) 232 if (!test_bit_inv(iv->end - 1, iv->avail))
236 break; 233 break;
237 } 234 }
238 spin_unlock(&iv->lock); 235 spin_unlock(&iv->lock);
@@ -251,15 +248,13 @@ EXPORT_SYMBOL(airq_iv_free_bit);
251unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, 248unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
252 unsigned long end) 249 unsigned long end)
253{ 250{
254 const unsigned long be_to_le = BITS_PER_LONG - 1;
255 unsigned long bit; 251 unsigned long bit;
256 252
257 /* Find non-zero bit starting from 'ivs->next'. */ 253 /* Find non-zero bit starting from 'ivs->next'. */
258 bit = find_next_bit_left(iv->vector, end, start); 254 bit = find_next_bit_inv(iv->vector, end, start);
259 if (bit >= end) 255 if (bit >= end)
260 return -1UL; 256 return -1UL;
261 /* Clear interrupt bit (find left uses big-endian bit numbers) */ 257 clear_bit_inv(bit, iv->vector);
262 clear_bit(bit ^ be_to_le, iv->vector);
263 return bit; 258 return bit;
264} 259}
265EXPORT_SYMBOL(airq_iv_scan); 260EXPORT_SYMBOL(airq_iv_scan);