summaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-08-03 08:44:59 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-08-03 09:19:01 -0400
commitd1f0301b3333eef5efbfa1fe0f0edbea01863d5d (patch)
tree86c897e94952090eee579ed47f49cc7006c41fd6 /kernel/irq/manage.c
parent6b4703768268d09ac928c64474fd686adf4574f9 (diff)
genirq: Make force irq threading setup more robust
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
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index daeabd791d58..9a8b7ba9aa88 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1068,6 +1068,13 @@ static int irq_setup_forced_threading(struct irqaction *new)
1068 if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)) 1068 if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
1069 return 0; 1069 return 0;
1070 1070
1071 /*
1072 * No further action required for interrupts which are requested as
1073 * threaded interrupts already
1074 */
1075 if (new->handler == irq_default_primary_handler)
1076 return 0;
1077
1071 new->flags |= IRQF_ONESHOT; 1078 new->flags |= IRQF_ONESHOT;
1072 1079
1073 /* 1080 /*
@@ -1075,7 +1082,7 @@ static int irq_setup_forced_threading(struct irqaction *new)
1075 * thread handler. We force thread them as well by creating a 1082 * thread handler. We force thread them as well by creating a
1076 * secondary action. 1083 * secondary action.
1077 */ 1084 */
1078 if (new->handler != irq_default_primary_handler && new->thread_fn) { 1085 if (new->handler && new->thread_fn) {
1079 /* Allocate the secondary action */ 1086 /* Allocate the secondary action */
1080 new->secondary = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 1087 new->secondary = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
1081 if (!new->secondary) 1088 if (!new->secondary)