PCI/ERR: Use slot reset if available

The secondary bus reset may have link side effects that a hotplug capable
port may incorrectly react to.  Use the slot specific reset for hotplug
ports, fixing the undesirable link down-up handling during error
recovering.

Signed-off-by: Keith Busch <keith.busch@intel.com>
[bhelgaas: fold in
https://lore.kernel.org/linux-pci/20180926152326.14821-1-keith.busch@intel.com
for issue reported by Stephen Rothwell <sfr@canb.auug.org.au>]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Sinan Kaya <okaya@kernel.org>
This commit is contained in:
Keith Busch
2018-09-20 10:27:11 -06:00
committed by Bjorn Helgaas
parent 9d938ea53b
commit c4eed62a21
5 changed files with 41 additions and 3 deletions

View File

@@ -35,6 +35,8 @@
#include <linux/aer.h>
#include "pci.h"
DEFINE_MUTEX(pci_slot_mutex);
const char *pci_power_names[] = {
"error", "D0", "D1", "D2", "D3hot", "D3cold", "unknown",
};
@@ -5155,6 +5157,41 @@ static int pci_bus_reset(struct pci_bus *bus, int probe)
return ret;
}
/**
* pci_bus_error_reset - reset the bridge's subordinate bus
* @bridge: The parent device that connects to the bus to reset
*
* This function will first try to reset the slots on this bus if the method is
* available. If slot reset fails or is not available, this will fall back to a
* secondary bus reset.
*/
int pci_bus_error_reset(struct pci_dev *bridge)
{
struct pci_bus *bus = bridge->subordinate;
struct pci_slot *slot;
if (!bus)
return -ENOTTY;
mutex_lock(&pci_slot_mutex);
if (list_empty(&bus->slots))
goto bus_reset;
list_for_each_entry(slot, &bus->slots, list)
if (pci_probe_reset_slot(slot))
goto bus_reset;
list_for_each_entry(slot, &bus->slots, list)
if (pci_slot_reset(slot, 0))
goto bus_reset;
mutex_unlock(&pci_slot_mutex);
return 0;
bus_reset:
mutex_unlock(&pci_slot_mutex);
return pci_bus_reset(bridge->subordinate, 0);
}
/**
* pci_probe_reset_bus - probe whether a PCI bus can be reset
* @bus: PCI bus to probe