fixup_irqs() re-injects a pending interrupt on its new target CPU by looking at the outermost domain chip and invoking its irq_retrigger() callback directly. When the outermost chip does not implement irq_retrigger(), the pending interrupt is silently dropped, which can lead to lost interrupts on CPU hot-unplug.
Use irq_chip_retrigger_hierarchy() instead, which walks up the interrupt hierarchy until it finds a chip that implements irq_retrigger(). This fixes the issues for those chips which miss initializing irq_retrigger callback. While at it, use a scoped guard for desc->lock. VECTOR_RETRIGGERED is now set only when the retrigger succeeds instead of unconditionally, which is harmless today since apic_retrigger_irq() always returns 1. Suggested-by: Thomas Gleixner <[email protected]> Reviewed-by: Shradha Gupta <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Signed-off-by: Naman Jain <[email protected]> --- arch/x86/kernel/irq.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 30122f0b3af96..acdc1145cce6d 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -469,7 +469,7 @@ void fixup_irqs(void) unsigned int vector; struct irq_desc *desc; struct irq_data *data; - struct irq_chip *chip; + int ret; irq_migrate_all_off_this_cpu(); @@ -490,21 +490,19 @@ void fixup_irqs(void) * nothing else will touch it. */ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { - if (IS_ERR_OR_NULL(__this_cpu_read(vector_irq[vector]))) + desc = __this_cpu_read(vector_irq[vector]); + + if (IS_ERR_OR_NULL(desc)) continue; if (is_vector_pending(vector)) { - desc = __this_cpu_read(vector_irq[vector]); - - raw_spin_lock(&desc->lock); + guard(raw_spinlock)(&desc->lock); data = irq_desc_get_irq_data(desc); - chip = irq_data_get_irq_chip(data); - if (chip->irq_retrigger) { - chip->irq_retrigger(data); + ret = irq_chip_retrigger_hierarchy(data); + if (ret) __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); - } - raw_spin_unlock(&desc->lock); } + if (__this_cpu_read(vector_irq[vector]) != VECTOR_RETRIGGERED) __this_cpu_write(vector_irq[vector], VECTOR_UNUSED); } -- 2.43.0
