Skip to content
  • Lukas Wunner's avatar
    PCI/ASPM: Fix link_state teardown on device removal · aeae4f3e
    Lukas Wunner authored
    Upon removal of the last device on a bus, the link_state of the bridge
    leading to that bus is sought to be torn down by having pci_stop_dev()
    call pcie_aspm_exit_link_state().
    
    When ASPM was originally introduced by commit 7d715a6c ("PCI: add
    PCI Express ASPM support"), it determined whether the device being
    removed is the last one by calling list_empty() on the bridge's
    subordinate devices list.  That didn't work because the device is only
    removed from the list slightly later in pci_destroy_dev().
    
    Commit 3419c75e ("PCI: properly clean up ASPM link state on device
    remove") attempted to fix it by calling list_is_last(), but that's not
    correct either because it checks whether the device is at the *end* of
    the list, not whether it's the last one *left* in the list.  If the user
    removes the device which happens to be at the end of the list via sysfs
    but other devices are preceding the device in the list, the link_state
    is torn down prematurely.
    
    The real fix is to move the invocation of pcie_aspm_exit_link_state() to
    pci_destroy_dev() and reinstate the call to list_empty().  Remove a
    duplicate check for dev->bus->self because pcie_aspm_exit_link_state()
    already contains an identical check.
    
    Fixes: 7d715a6c
    
     ("PCI: add PCI Express ASPM support")
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Cc: Shaohua Li <shaohua.li@intel.com>
    Cc: stable@vger.kernel.org # v2.6.26
    aeae4f3e