mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
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>
This commit is contained in:
parent
646f919e93
commit
0eb69a0c58
@ -196,11 +196,11 @@ EXPORT_SYMBOL(airq_iv_release);
|
||||
*/
|
||||
unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
|
||||
{
|
||||
unsigned long bit, i;
|
||||
unsigned long bit, i, flags;
|
||||
|
||||
if (!iv->avail || num == 0)
|
||||
return -1UL;
|
||||
spin_lock(&iv->lock);
|
||||
spin_lock_irqsave(&iv->lock, flags);
|
||||
bit = find_first_bit_inv(iv->avail, iv->bits);
|
||||
while (bit + num <= iv->bits) {
|
||||
for (i = 1; i < num; i++)
|
||||
@ -218,9 +218,8 @@ unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
|
||||
}
|
||||
if (bit + num > iv->bits)
|
||||
bit = -1UL;
|
||||
spin_unlock(&iv->lock);
|
||||
spin_unlock_irqrestore(&iv->lock, flags);
|
||||
return bit;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(airq_iv_alloc);
|
||||
|
||||
@ -232,11 +231,11 @@ EXPORT_SYMBOL(airq_iv_alloc);
|
||||
*/
|
||||
void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long i, flags;
|
||||
|
||||
if (!iv->avail || num == 0)
|
||||
return;
|
||||
spin_lock(&iv->lock);
|
||||
spin_lock_irqsave(&iv->lock, flags);
|
||||
for (i = 0; i < num; i++) {
|
||||
/* Clear (possibly left over) interrupt bit */
|
||||
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)
|
||||
while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail))
|
||||
iv->end--;
|
||||
}
|
||||
spin_unlock(&iv->lock);
|
||||
spin_unlock_irqrestore(&iv->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(airq_iv_free);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user