diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-13 13:47:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-13 13:47:26 -0400 |
commit | d0daaeaf60143c02a2ef87f9f0703b63a0a7f8b3 (patch) | |
tree | 37117a1589f55f3b103e71f6180c66b47c6bfdea /kernel/irq/manage.c | |
parent | 400439275d9543286f9d3f2925c3156f888e6b18 (diff) | |
parent | 9e90c7985229430428dc9ba0ec7fe422901b456d (diff) |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull genirq updates from Thomas Gleixner:
"The irq departement provides:
- A synchronization fix for free_irq() to synchronize just the
removed interrupt thread on shared interrupt lines.
- Consolidate the multi low level interrupt entry handling and mvoe
it to the generic code instead of adding yet another copy for
RISC-V
- Refactoring of the ARM LPI allocator and LPI exposure to the
hypervisor
- Yet another interrupt chip driver for the JZ4725B SoC
- Speed up for /proc/interrupts as people seem to love reading this
file with high frequency
- Miscellaneous fixes and updates"
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
irqchip/gic-v3-its: Make its_lock a raw_spin_lock_t
genirq/irqchip: Remove MULTI_IRQ_HANDLER as it's now obselete
openrisc: Use the new GENERIC_IRQ_MULTI_HANDLER
arm64: Use the new GENERIC_IRQ_MULTI_HANDLER
ARM: Convert to GENERIC_IRQ_MULTI_HANDLER
irqchip: Port the ARM IRQ drivers to GENERIC_IRQ_MULTI_HANDLER
irqchip/gic-v3-its: Reduce minimum LPI allocation to 1 for PCI devices
dt-bindings: irqchip: renesas-irqc: Document r8a77980 support
dt-bindings: irqchip: renesas-irqc: Document r8a77470 support
irqchip/ingenic: Add support for the JZ4725B SoC
irqchip/stm32: Add exti0 translation for stm32mp1
genirq: Remove redundant NULL pointer check in __free_irq()
irqchip/gic-v3-its: Honor hypervisor enforced LPI range
irqchip/gic-v3: Expose GICD_TYPER in the rdist structure
irqchip/gic-v3-its: Drop chunk allocation compatibility
irqchip/gic-v3-its: Move minimum LPI requirements to individual busses
irqchip/gic-v3-its: Use full range of LPIs
irqchip/gic-v3-its: Refactor LPI allocator
genirq: Synchronize only with single thread on free_irq()
genirq: Update code comments wrt recycled thread_mask
...
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 9a8b7ba9aa88..fb86146037a7 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -790,9 +790,19 @@ static irqreturn_t irq_forced_secondary_handler(int irq, void *dev_id) | |||
790 | 790 | ||
791 | static int irq_wait_for_interrupt(struct irqaction *action) | 791 | static int irq_wait_for_interrupt(struct irqaction *action) |
792 | { | 792 | { |
793 | set_current_state(TASK_INTERRUPTIBLE); | 793 | for (;;) { |
794 | set_current_state(TASK_INTERRUPTIBLE); | ||
794 | 795 | ||
795 | while (!kthread_should_stop()) { | 796 | if (kthread_should_stop()) { |
797 | /* may need to run one last time */ | ||
798 | if (test_and_clear_bit(IRQTF_RUNTHREAD, | ||
799 | &action->thread_flags)) { | ||
800 | __set_current_state(TASK_RUNNING); | ||
801 | return 0; | ||
802 | } | ||
803 | __set_current_state(TASK_RUNNING); | ||
804 | return -1; | ||
805 | } | ||
796 | 806 | ||
797 | if (test_and_clear_bit(IRQTF_RUNTHREAD, | 807 | if (test_and_clear_bit(IRQTF_RUNTHREAD, |
798 | &action->thread_flags)) { | 808 | &action->thread_flags)) { |
@@ -800,10 +810,7 @@ static int irq_wait_for_interrupt(struct irqaction *action) | |||
800 | return 0; | 810 | return 0; |
801 | } | 811 | } |
802 | schedule(); | 812 | schedule(); |
803 | set_current_state(TASK_INTERRUPTIBLE); | ||
804 | } | 813 | } |
805 | __set_current_state(TASK_RUNNING); | ||
806 | return -1; | ||
807 | } | 814 | } |
808 | 815 | ||
809 | /* | 816 | /* |
@@ -1024,11 +1031,8 @@ static int irq_thread(void *data) | |||
1024 | /* | 1031 | /* |
1025 | * This is the regular exit path. __free_irq() is stopping the | 1032 | * This is the regular exit path. __free_irq() is stopping the |
1026 | * thread via kthread_stop() after calling | 1033 | * thread via kthread_stop() after calling |
1027 | * synchronize_irq(). So neither IRQTF_RUNTHREAD nor the | 1034 | * synchronize_hardirq(). So neither IRQTF_RUNTHREAD nor the |
1028 | * oneshot mask bit can be set. We cannot verify that as we | 1035 | * oneshot mask bit can be set. |
1029 | * cannot touch the oneshot mask at this point anymore as | ||
1030 | * __setup_irq() might have given out currents thread_mask | ||
1031 | * again. | ||
1032 | */ | 1036 | */ |
1033 | task_work_cancel(current, irq_thread_dtor); | 1037 | task_work_cancel(current, irq_thread_dtor); |
1034 | return 0; | 1038 | return 0; |
@@ -1251,8 +1255,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1251 | 1255 | ||
1252 | /* | 1256 | /* |
1253 | * Protects against a concurrent __free_irq() call which might wait | 1257 | * Protects against a concurrent __free_irq() call which might wait |
1254 | * for synchronize_irq() to complete without holding the optional | 1258 | * for synchronize_hardirq() to complete without holding the optional |
1255 | * chip bus lock and desc->lock. | 1259 | * chip bus lock and desc->lock. Also protects against handing out |
1260 | * a recycled oneshot thread_mask bit while it's still in use by | ||
1261 | * its previous owner. | ||
1256 | */ | 1262 | */ |
1257 | mutex_lock(&desc->request_mutex); | 1263 | mutex_lock(&desc->request_mutex); |
1258 | 1264 | ||
@@ -1571,9 +1577,6 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) | |||
1571 | 1577 | ||
1572 | WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); | 1578 | WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); |
1573 | 1579 | ||
1574 | if (!desc) | ||
1575 | return NULL; | ||
1576 | |||
1577 | mutex_lock(&desc->request_mutex); | 1580 | mutex_lock(&desc->request_mutex); |
1578 | chip_bus_lock(desc); | 1581 | chip_bus_lock(desc); |
1579 | raw_spin_lock_irqsave(&desc->lock, flags); | 1582 | raw_spin_lock_irqsave(&desc->lock, flags); |
@@ -1620,11 +1623,11 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) | |||
1620 | /* | 1623 | /* |
1621 | * Drop bus_lock here so the changes which were done in the chip | 1624 | * Drop bus_lock here so the changes which were done in the chip |
1622 | * callbacks above are synced out to the irq chips which hang | 1625 | * callbacks above are synced out to the irq chips which hang |
1623 | * behind a slow bus (I2C, SPI) before calling synchronize_irq(). | 1626 | * behind a slow bus (I2C, SPI) before calling synchronize_hardirq(). |
1624 | * | 1627 | * |
1625 | * Aside of that the bus_lock can also be taken from the threaded | 1628 | * Aside of that the bus_lock can also be taken from the threaded |
1626 | * handler in irq_finalize_oneshot() which results in a deadlock | 1629 | * handler in irq_finalize_oneshot() which results in a deadlock |
1627 | * because synchronize_irq() would wait forever for the thread to | 1630 | * because kthread_stop() would wait forever for the thread to |
1628 | * complete, which is blocked on the bus lock. | 1631 | * complete, which is blocked on the bus lock. |
1629 | * | 1632 | * |
1630 | * The still held desc->request_mutex() protects against a | 1633 | * The still held desc->request_mutex() protects against a |
@@ -1636,7 +1639,7 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) | |||
1636 | unregister_handler_proc(irq, action); | 1639 | unregister_handler_proc(irq, action); |
1637 | 1640 | ||
1638 | /* Make sure it's not being used on another CPU: */ | 1641 | /* Make sure it's not being used on another CPU: */ |
1639 | synchronize_irq(irq); | 1642 | synchronize_hardirq(irq); |
1640 | 1643 | ||
1641 | #ifdef CONFIG_DEBUG_SHIRQ | 1644 | #ifdef CONFIG_DEBUG_SHIRQ |
1642 | /* | 1645 | /* |
@@ -1645,7 +1648,7 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) | |||
1645 | * is so by doing an extra call to the handler .... | 1648 | * is so by doing an extra call to the handler .... |
1646 | * | 1649 | * |
1647 | * ( We do this after actually deregistering it, to make sure that a | 1650 | * ( We do this after actually deregistering it, to make sure that a |
1648 | * 'real' IRQ doesn't run in * parallel with our fake. ) | 1651 | * 'real' IRQ doesn't run in parallel with our fake. ) |
1649 | */ | 1652 | */ |
1650 | if (action->flags & IRQF_SHARED) { | 1653 | if (action->flags & IRQF_SHARED) { |
1651 | local_irq_save(flags); | 1654 | local_irq_save(flags); |
@@ -1654,6 +1657,12 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) | |||
1654 | } | 1657 | } |
1655 | #endif | 1658 | #endif |
1656 | 1659 | ||
1660 | /* | ||
1661 | * The action has already been removed above, but the thread writes | ||
1662 | * its oneshot mask bit when it completes. Though request_mutex is | ||
1663 | * held across this which prevents __setup_irq() from handing out | ||
1664 | * the same bit to a newly requested action. | ||
1665 | */ | ||
1657 | if (action->thread) { | 1666 | if (action->thread) { |
1658 | kthread_stop(action->thread); | 1667 | kthread_stop(action->thread); |
1659 | put_task_struct(action->thread); | 1668 | put_task_struct(action->thread); |