[RFC PATCH 45/49] irq_work: Introduce irq_work_kick_cpu()

From: Frederic Weisbecker

Date: Mon Oct 19 2026 - 09:29:56 EST


CPUs in nohz mode need to be kicked in the following situations:

* A tick dependency has been added to a CPU that must exit the nohz_full
mode. The tick infrastructure has its own ad-hoc implementation of
such a "kick".

* A timekeeper going offline needs to handover its timekeeping duty
to another CPU. This is currently assigned directly in stop_machine()
with the assumption that the new timekeeper is not in dynticks-idle
mode. But since teardown callbacks are being converted to execute
concurrently with other CPUs, the new timekeeper may now be idle.
It so, it must get an IRQ so that the next tick is reevaluated.

Provide a generic empty irq work callback to implement this "kick".

Signed-off-by: Frederic Weisbecker <frederic@xxxxxxxxxx>
---
include/linux/irq_work.h | 1 +
kernel/irq_work.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)

diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
index c5afd053ae32..3873f4ff5be4 100644
--- a/include/linux/irq_work.h
+++ b/include/linux/irq_work.h
@@ -51,6 +51,7 @@ static inline bool irq_work_is_hard(struct irq_work *work)

bool irq_work_queue(struct irq_work *work);
bool irq_work_queue_on(struct irq_work *work, int cpu);
+bool irq_work_kick_cpu(int cpu);

void irq_work_tick(void);
void irq_work_sync(struct irq_work *work);
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index f7e2dc2c30c6..a1569266ec35 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -181,6 +181,22 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
#endif /* CONFIG_SMP */
}

+static void irq_work_kick(struct irq_work *unused)
+{
+ /*
+ * Kick the CPU, typically so that it takes action:
+ * * On IRQ exit (nohz_full dependency changed and tick must be restarted)
+ * * On the idle path so that the next tick is re-evaluated.
+ */
+}
+
+static DEFINE_PER_CPU(struct irq_work, irq_work_kick_work) = IRQ_WORK_INIT_HARD(irq_work_kick);
+
+bool irq_work_kick_cpu(int cpu)
+{
+ return irq_work_queue_on(&per_cpu(irq_work_kick_work, cpu), cpu);
+}
+
bool irq_work_needs_cpu(void)
{
struct llist_head *raised, *lazy;
--
2.53.0