Re: [PATCH 1/6] irq_work: Re-raise pending irq_work after system resume

From: Peter Zijlstra

Date: Mon Nov 02 2026 - 04:09:56 EST


On Mon, Nov 02, 2026 at 09:40:34AM +0200, Adrian Hunter wrote:
> irq_work_queue() raises the irq_work self-interrupt only when adding
> work to an empty raised_list. Once raised_list is non-empty, further
> queueing assumes the interrupt is already pending and will eventually
> process the list.
>
> That assumption can fail across system suspend. irq_work queued after
> arch_suspend_disable_irqs() and before the interrupt controller is
> suspended, for example from NMI context, may leave its self-interrupt
> pending in hardware. If that pending interrupt state is lost during
> suspend, hibernation restore, or kexec jump, raised_list remains
> non-empty after resume but nothing will process it.
>
> Subsequent irq_work added to raised_list will not raise another
> interrupt because the list is already non-empty. Architectures that use
> an irq_work interrupt and do not process raised_list from the tick can
> therefore leave irq_work pending indefinitely. A caller waiting in
> irq_work_sync() may then spin forever, for example when closing a perf
> event whose pending irq_work never executes.
>
> For suspend, hibernation, and kexec jump, only the CPU that remains
> online is affected. The other CPUs are taken offline beforehand, and
> smpcfd_dying_cpu() runs irq_work_run() on each CPU before it is removed,
> so checking the local raised_list is sufficient.

I thought here was a suspend2idle option where all the CPUs remain
online?

Anyway, I'm torn; I would much rather make this trigger a WARN and have
suspend pause/resume perf in a more controlled manner. Also, ISTR there
being hooks in kexec, but I can't seem to find them :/