]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
genirq: Prevent early spurious wake-ups of interrupt threads
authorFrederic Weisbecker <frederic@kernel.org>
Fri, 21 Nov 2025 14:34:58 +0000 (15:34 +0100)
committerIngo Molnar <mingo@kernel.org>
Sat, 22 Nov 2025 08:26:18 +0000 (09:26 +0100)
During initialization, the interrupt thread is created before the interrupt
is enabled. The interrupt enablement happens before the actual kthread wake
up point. Once the interrupt is enabled the hardware can raise an interrupt
and once setup_irq() drops the descriptor lock a interrupt wake-up can
happen.

Even when such an interrupt can be considered premature, this is not a
problem in general because at the point where the descriptor lock is
dropped and the wakeup can happen, the data which is used by the thread is
fully initialized.

Though from the perspective of least surprise, the initial wakeup really
should be performed by the setup code and not randomly by a premature
interrupt.

Prevent this by performing a wake-up only if the target is in state
TASK_INTERRUPTIBLE, which the thread uses in wait_for_interrupt().

If the thread is still in state TASK_UNINTERRUPTIBLE, the wake-up is not
lost because after the setup code completed the initial wake-up the thread
will observe the IRQTF_RUNTHREAD and proceed with the handling.

[ tglx: Simplified the changes and extended the changelog. ]

Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://patch.msgid.link/20251121143500.42111-2-frederic@kernel.org
kernel/irq/handle.c

index e103451243a0b6857543b836020cc5b5c9501780..786f5570a640736f56437604c63eb1a0bd416c7a 100644 (file)
@@ -133,7 +133,15 @@ void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
         */
        atomic_inc(&desc->threads_active);
 
-       wake_up_process(action->thread);
+       /*
+        * This might be a premature wakeup before the thread reached the
+        * thread function and set the IRQTF_READY bit. It's waiting in
+        * kthread code with state UNINTERRUPTIBLE. Once it reaches the
+        * thread function it waits with INTERRUPTIBLE. The wakeup is not
+        * lost in that case because the thread is guaranteed to observe
+        * the RUN flag before it goes to sleep in wait_for_interrupt().
+        */
+       wake_up_state(action->thread, TASK_INTERRUPTIBLE);
 }
 
 static DEFINE_STATIC_KEY_FALSE(irqhandler_duration_check_enabled);