| From d1f0301b3333eef5efbfa1fe0f0edbea01863d5d Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Fri, 3 Aug 2018 14:44:59 +0200 |
| Subject: genirq: Make force irq threading setup more robust |
| |
| From: Thomas Gleixner <tglx@linutronix.de> |
| |
| commit d1f0301b3333eef5efbfa1fe0f0edbea01863d5d upstream. |
| |
| The support of force threading interrupts which are set up with both a |
| primary and a threaded handler wreckaged the setup of regular requested |
| threaded interrupts (primary handler == NULL). |
| |
| The reason is that it does not check whether the primary handler is set to |
| the default handler which wakes the handler thread. Instead it replaces the |
| thread handler with the primary handler as it would do with force threaded |
| interrupts which have been requested via request_irq(). So both the primary |
| and the thread handler become the same which then triggers the warnon that |
| the thread handler tries to wakeup a not configured secondary thread. |
| |
| Fortunately this only happens when the driver omits the IRQF_ONESHOT flag |
| when requesting the threaded interrupt, which is normaly caught by the |
| sanity checks when force irq threading is disabled. |
| |
| Fix it by skipping the force threading setup when a regular threaded |
| interrupt is requested. As a consequence the interrupt request which lacks |
| the IRQ_ONESHOT flag is rejected correctly instead of silently wreckaging |
| it. |
| |
| Fixes: 2a1d3ab8986d ("genirq: Handle force threading of irqs with primary and thread handler") |
| Reported-by: Kurt Kanzenbach <kurt.kanzenbach@linutronix.de> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Tested-by: Kurt Kanzenbach <kurt.kanzenbach@linutronix.de> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/irq/manage.c | 9 ++++++++- |
| 1 file changed, 8 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/irq/manage.c |
| +++ b/kernel/irq/manage.c |
| @@ -1026,6 +1026,13 @@ static int irq_setup_forced_threading(st |
| if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)) |
| return 0; |
| |
| + /* |
| + * No further action required for interrupts which are requested as |
| + * threaded interrupts already |
| + */ |
| + if (new->handler == irq_default_primary_handler) |
| + return 0; |
| + |
| new->flags |= IRQF_ONESHOT; |
| |
| /* |
| @@ -1033,7 +1040,7 @@ static int irq_setup_forced_threading(st |
| * thread handler. We force thread them as well by creating a |
| * secondary action. |
| */ |
| - if (new->handler != irq_default_primary_handler && new->thread_fn) { |
| + if (new->handler && new->thread_fn) { |
| /* Allocate the secondary action */ |
| new->secondary = kzalloc(sizeof(struct irqaction), GFP_KERNEL); |
| if (!new->secondary) |