diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2014-06-05 08:30:19 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-06-10 04:48:30 -0400 |
commit | 0eb69a0c584d0eaec6c2b6663e03184625c3517b (patch) | |
tree | b12bec17e1646166bdbf96ab617c794e7edad6c2 /drivers/s390 | |
parent | 646f919e93d4371b8654c4ae801aee74a00e4a68 (diff) |
s390/airq: silence lockdep warning
airq_iv_(alloc|free) is called by some users with interrupts enabled
and by some with interrupts disabled which leads to the following
lockdep warning:
[ INFO: possible irq lock inversion dependency detected ]
3.14.0-15249-gbf29b7b-dirty #25 Not tainted
---------------------------------------------------------
insmod/2108 just changed the state of lock:
(&(&iv->lock)->rlock){+.....}, at: [<000000000046ee3e>] airq_iv_alloc+0x62/0x228
but this lock was taken by another, HARDIRQ-READ-safe lock in the past:
(&info->lock){.-.-..}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this:
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&(&iv->lock)->rlock);
local_irq_disable();
lock(&info->lock);
lock(&(&iv->lock)->rlock);
<Interrupt>
lock(&info->lock);
*** DEADLOCK ***
Although this is a false alarm (since each airq user consistently
calls these functions from the same context) fix this by ensuring
that interrupts are disabled when the airq lock is held.
Reported-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/airq.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 445564c790f6..00bfbee0af9e 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c | |||
@@ -196,11 +196,11 @@ EXPORT_SYMBOL(airq_iv_release); | |||
196 | */ | 196 | */ |
197 | unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num) | 197 | unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num) |
198 | { | 198 | { |
199 | unsigned long bit, i; | 199 | unsigned long bit, i, flags; |
200 | 200 | ||
201 | if (!iv->avail || num == 0) | 201 | if (!iv->avail || num == 0) |
202 | return -1UL; | 202 | return -1UL; |
203 | spin_lock(&iv->lock); | 203 | spin_lock_irqsave(&iv->lock, flags); |
204 | bit = find_first_bit_inv(iv->avail, iv->bits); | 204 | bit = find_first_bit_inv(iv->avail, iv->bits); |
205 | while (bit + num <= iv->bits) { | 205 | while (bit + num <= iv->bits) { |
206 | for (i = 1; i < num; i++) | 206 | for (i = 1; i < num; i++) |
@@ -218,9 +218,8 @@ unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num) | |||
218 | } | 218 | } |
219 | if (bit + num > iv->bits) | 219 | if (bit + num > iv->bits) |
220 | bit = -1UL; | 220 | bit = -1UL; |
221 | spin_unlock(&iv->lock); | 221 | spin_unlock_irqrestore(&iv->lock, flags); |
222 | return bit; | 222 | return bit; |
223 | |||
224 | } | 223 | } |
225 | EXPORT_SYMBOL(airq_iv_alloc); | 224 | EXPORT_SYMBOL(airq_iv_alloc); |
226 | 225 | ||
@@ -232,11 +231,11 @@ EXPORT_SYMBOL(airq_iv_alloc); | |||
232 | */ | 231 | */ |
233 | void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num) | 232 | void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num) |
234 | { | 233 | { |
235 | unsigned long i; | 234 | unsigned long i, flags; |
236 | 235 | ||
237 | if (!iv->avail || num == 0) | 236 | if (!iv->avail || num == 0) |
238 | return; | 237 | return; |
239 | spin_lock(&iv->lock); | 238 | spin_lock_irqsave(&iv->lock, flags); |
240 | for (i = 0; i < num; i++) { | 239 | for (i = 0; i < num; i++) { |
241 | /* Clear (possibly left over) interrupt bit */ | 240 | /* Clear (possibly left over) interrupt bit */ |
242 | clear_bit_inv(bit + i, iv->vector); | 241 | clear_bit_inv(bit + i, iv->vector); |
@@ -248,7 +247,7 @@ void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num) | |||
248 | while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail)) | 247 | while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail)) |
249 | iv->end--; | 248 | iv->end--; |
250 | } | 249 | } |
251 | spin_unlock(&iv->lock); | 250 | spin_unlock_irqrestore(&iv->lock, flags); |
252 | } | 251 | } |
253 | EXPORT_SYMBOL(airq_iv_free); | 252 | EXPORT_SYMBOL(airq_iv_free); |
254 | 253 | ||