• Stuart Hayes's avatar
    PCI: pciehp: Fix MSI interrupt race · 8edf5332
    Stuart Hayes authored
    Without this commit, a PCIe hotplug port can stop generating interrupts on
    hotplug events, so device adds and removals will not be seen:
    
    The pciehp interrupt handler pciehp_isr() reads the Slot Status register
    and then writes back to it to clear the bits that caused the interrupt.  If
    a different interrupt event bit gets set between the read and the write,
    pciehp_isr() returns without having cleared all of the interrupt event
    bits.  If this happens when the MSI isn't masked (which by default it isn't
    in handle_edge_irq(), and which it will never be when MSI per-vector
    masking is not supported), we won't get any more hotplug interrupts from
    that device.
    
    That is expected behavior, according to the PCIe Base Spec r5.0, section
    6.7.3.4, "Software Notification of Hot-Plug Events".
    
    Because the Presence Detect Changed and Data Link Layer State Changed event
    bits can both get set at nearly the same time when a device is added or
    removed, this is more likely to happen than it might seem.  The issue was
    found (and can be reproduced rather easily) by connecting and disconnecting
    an NVMe storage device on at least one system model where the NVMe devices
    were being connected to an AMD PCIe port (PCI device 0x1022/0x1483).
    
    Fix the issue by modifying pciehp_isr() to loop back and re-read the Slot
    Status register immediately after writing to it, until it sees that all of
    the event status bits have been cleared.
    
    [lukas: drop loop count limitation, write "events" instead of "status",
    don't loop back in INTx and poll modes, tweak code comment & commit msg]
    Link: https://lore.kernel.org/r/78b4ced5072bfe6e369d20e8b47c279b8c7af12e.1582121613.git.lukas@wunner.deTested-by: default avatarStuart Hayes <stuart.w.hayes@gmail.com>
    Signed-off-by: default avatarStuart Hayes <stuart.w.hayes@gmail.com>
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Reviewed-by: default avatarJoerg Roedel <jroedel@suse.de>
    8edf5332
pciehp_hpc.c 27.3 KB