• Thomas Gleixner's avatar
    x86/ioapic: Implement irq_get_irqchip_state() callback · dfe0cf8b
    Thomas Gleixner authored
    When an interrupt is shut down in free_irq() there might be an inflight
    interrupt pending in the IO-APIC remote IRR which is not yet serviced. That
    means the interrupt has been sent to the target CPUs local APIC, but the
    target CPU is in a state which delays the servicing.
    
    So free_irq() would proceed to free resources and to clear the vector
    because synchronize_hardirq() does not see an interrupt handler in
    progress.
    
    That can trigger a spurious interrupt warning, which is harmless and just
    confuses users, but it also can leave the remote IRR in a stale state
    because once the handler is invoked the interrupt resources might be freed
    already and therefore acknowledgement is not possible anymore.
    
    Implement the irq_get_irqchip_state() callback for the IO-APIC irq chip. The
    callback is invoked from free_irq() via __synchronize_hardirq(). Check the
    remote IRR bit of the interrupt and return 'in flight' if it is set and the
    interrupt is configured in level mode. For edge mode the remote IRR has no
    meaning.
    
    As this is only meaningful for level triggered interrupts this won't cure
    the potential spurious interrupt warning for edge triggered interrupts, but
    the edge trigger case does not result in stale hardware state. This has to
    be addressed at the vector/interrupt entry level seperately.
    
    Fixes: 464d1230 ("x86/vector: Switch IOAPIC to global reservation mode")
    Reported-by: default avatarRobert Hodaszi <Robert.Hodaszi@digi.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Marc Zyngier <marc.zyngier@arm.com>
    Link: https://lkml.kernel.org/r/20190628111440.370295517@linutronix.de
    dfe0cf8b
io_apic.c 79.1 KB