summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2026-09-11 16:38:13 +0200
committerPeter Zijlstra <peterz@infradead.org>2026-10-01 14:00:35 +0200
commit40dcc9bdbef3d93a516c8ee32cb1b50eddeeebcc (patch)
tree62cf07ee524da15e7ea10cf96c24fa37c3ca4914 /include/linux
parent791b1760accdc15248929f9b767410a76be199b1 (diff)
downloadlinux-next-40dcc9bdbef3d93a516c8ee32cb1b50eddeeebcc.tar.gz
linux-next-40dcc9bdbef3d93a516c8ee32cb1b50eddeeebcc.zip
irq_work: Flush lazy work CPU down on PREEMPT_RT
PREEMPT_RT invokes IRQ_WORK_LAZY callbacks and callbacks which are not explicitly marked IRQ_WORK_HARD_IRQ from thread context. If a CPU gets shutdown, the irq_work is flushed during smpcfd_dying_cpu() which is invoked on the target CPU with disabled interrupts. The callbacks enqueued on lazy_list on PREEMPT_RT are not flushed because they require thread context. The callbacks remain and get processed once the CPU gets back online. per-CPU irq_work items continue to work for enqueues on their local-CPU, only the work on the "offline" CPU get stuck. "Single" irq_work are worse because they remain "claimed" and can not be used again. One "symptom" is the late printk() in CPU down path which enqueues the irq_work for printing but it never gets scheduled. Further prints don't print to the console because the irq_work is "pending" of the offline CPU. Another problem is the canceling/ flushing of the irq_work which is stuck. Since the irq_work will not continue, the task waiting for its completion will block waiting. While looking through the users of irq_work, it does not matter if the callback is enqueued on another CPU. This makes it possible to invoke the callbacks from a remote CPU by smpcfd_dead_cpu(). This is invoked from the control CPU with enabled interrupts shortly after the hotplugged CPU is shutdown so the llist can be accessed safely. Add irq_work_run_cpu() which invokes the irq_work callbacks of the specified dead CPU. Invoke it from smpcfd_dead_cpu(). Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20260911143815.997254-3-bigeasy@linutronix.de
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/irq_work.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
index c5afd053ae32..7184e1273965 100644
--- a/include/linux/irq_work.h
+++ b/include/linux/irq_work.h
@@ -59,6 +59,7 @@ void irq_work_sync(struct irq_work *work);
#include <asm/irq_work.h>
void irq_work_run(void);
+void irq_work_run_cpu(unsigned int cpu);
bool irq_work_needs_cpu(void);
void irq_work_single(void *arg);
@@ -67,6 +68,7 @@ void arch_irq_work_raise(void);
#else
static inline bool irq_work_needs_cpu(void) { return false; }
static inline void irq_work_run(void) { }
+static inline void irq_work_run_cpu(unsigned int cpu) { }
static inline void irq_work_single(void *arg) { }
#endif