diff options
-rw-r--r-- | arch/s390/include/asm/bitops.h | 39 | ||||
-rw-r--r-- | arch/s390/lib/find.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/airq.c | 19 |
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 | */ |
306 | unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size); | 309 | unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size); |
307 | unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, | 310 | unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, |
308 | unsigned long offset); | 311 | unsigned long offset); |
312 | |||
313 | static 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 | |||
318 | static 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 | |||
323 | static 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 | |||
328 | static 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 | |||
333 | static 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 | ||
18 | unsigned long find_first_bit_left(const unsigned long *addr, unsigned long size) | 18 | unsigned 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) | |||
35 | found: | 35 | found: |
36 | return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); | 36 | return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); |
37 | } | 37 | } |
38 | EXPORT_SYMBOL(find_first_bit_left); | 38 | EXPORT_SYMBOL(find_first_bit_inv); |
39 | 39 | ||
40 | unsigned long find_next_bit_left(const unsigned long *addr, unsigned long size, | 40 | unsigned 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: | |||
74 | found_middle: | 74 | found_middle: |
75 | return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); | 75 | return result + (__fls(tmp) ^ (BITS_PER_LONG - 1)); |
76 | } | 76 | } |
77 | EXPORT_SYMBOL(find_next_bit_left); | 77 | 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); | |||
194 | */ | 194 | */ |
195 | unsigned long airq_iv_alloc_bit(struct airq_iv *iv) | 195 | unsigned 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 | */ |
221 | void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) | 220 | void 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); | |||
251 | unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, | 248 | unsigned 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 | } |
265 | EXPORT_SYMBOL(airq_iv_scan); | 260 | EXPORT_SYMBOL(airq_iv_scan); |