diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-06-29 17:33:37 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-07-04 06:46:16 -0400 |
commit | 9114014cf4e6df0b22d764380ae1fc54f1a7a8b2 (patch) | |
tree | 11be4a12a5d75cc271cdcaa26736e1855048acdd /kernel/irq/manage.c | |
parent | 3a90795e1e885167209056a1a90be965add30e25 (diff) |
genirq: Add mutex to irq desc to serialize request/free_irq()
The irq_request/release_resources() callbacks ar currently invoked under
desc->lock with interrupts disabled. This is a source of problems on RT and
conceptually not required.
Add a seperate mutex to struct irq_desc which allows to serialize
request/free_irq(), which can be used to move the resource functions out of
the desc->lock held region.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Julia Cartwright <julia@ni.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Brian Norris <briannorris@chromium.org>
Cc: Doug Anderson <dianders@chromium.org>
Cc: linux-rockchip@lists.infradead.org
Cc: John Keeping <john@metanate.com>
Cc: linux-gpio@vger.kernel.org
Link: http://lkml.kernel.org/r/20170629214344.039220922@linutronix.de
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0934e02fa04e..0139908b8d53 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -1167,6 +1167,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1167 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) | 1167 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) |
1168 | new->flags &= ~IRQF_ONESHOT; | 1168 | new->flags &= ~IRQF_ONESHOT; |
1169 | 1169 | ||
1170 | mutex_lock(&desc->request_mutex); | ||
1171 | |||
1170 | chip_bus_lock(desc); | 1172 | chip_bus_lock(desc); |
1171 | 1173 | ||
1172 | /* | 1174 | /* |
@@ -1350,6 +1352,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1350 | 1352 | ||
1351 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 1353 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
1352 | chip_bus_sync_unlock(desc); | 1354 | chip_bus_sync_unlock(desc); |
1355 | mutex_unlock(&desc->request_mutex); | ||
1353 | 1356 | ||
1354 | irq_setup_timings(desc, new); | 1357 | irq_setup_timings(desc, new); |
1355 | 1358 | ||
@@ -1383,6 +1386,8 @@ out_unlock: | |||
1383 | 1386 | ||
1384 | chip_bus_sync_unlock(desc); | 1387 | chip_bus_sync_unlock(desc); |
1385 | 1388 | ||
1389 | mutex_unlock(&desc->request_mutex); | ||
1390 | |||
1386 | out_thread: | 1391 | out_thread: |
1387 | if (new->thread) { | 1392 | if (new->thread) { |
1388 | struct task_struct *t = new->thread; | 1393 | struct task_struct *t = new->thread; |
@@ -1446,6 +1451,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
1446 | if (!desc) | 1451 | if (!desc) |
1447 | return NULL; | 1452 | return NULL; |
1448 | 1453 | ||
1454 | mutex_lock(&desc->request_mutex); | ||
1449 | chip_bus_lock(desc); | 1455 | chip_bus_lock(desc); |
1450 | raw_spin_lock_irqsave(&desc->lock, flags); | 1456 | raw_spin_lock_irqsave(&desc->lock, flags); |
1451 | 1457 | ||
@@ -1521,6 +1527,8 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
1521 | } | 1527 | } |
1522 | } | 1528 | } |
1523 | 1529 | ||
1530 | mutex_unlock(&desc->request_mutex); | ||
1531 | |||
1524 | irq_chip_pm_put(&desc->irq_data); | 1532 | irq_chip_pm_put(&desc->irq_data); |
1525 | module_put(desc->owner); | 1533 | module_put(desc->owner); |
1526 | kfree(action->secondary); | 1534 | kfree(action->secondary); |