Skip to content

Commit

Permalink
PCI: Add failed link recovery for device reset events
Browse files Browse the repository at this point in the history
Request failed link recovery with any upstream PCIe bridge where a device
has not come back after reset within PCI_RESET_WAIT time.  Reset the
polling interval if recovery succeeded, otherwise continue as usual.

[bhelgaas: inline pcie_parent_link_retrain()]
Link: https://lore.kernel.org/r/alpine.DEB.2.21.2306111631050.64925@angie.orcam.me.uk
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
  • Loading branch information
Maciej W. Rozycki authored and Bjorn Helgaas committed Jun 20, 2023
1 parent a89c822 commit 08e3ed1
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,14 @@ void pci_resume_bus(struct pci_bus *bus)
static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
{
int delay = 1;
u32 id;
bool retrain = false;
struct pci_dev *bridge;

if (pci_is_pcie(dev)) {
bridge = pci_upstream_bridge(dev);
if (bridge)
retrain = true;
}

/*
* After reset, the device should not silently discard config
Expand All @@ -1170,21 +1177,33 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
* Command register instead of Vendor ID so we don't have to
* contend with the CRS SV value.
*/
pci_read_config_dword(dev, PCI_COMMAND, &id);
while (PCI_POSSIBLE_ERROR(id)) {
for (;;) {
u32 id;

pci_read_config_dword(dev, PCI_COMMAND, &id);
if (!PCI_POSSIBLE_ERROR(id))
break;

if (delay > timeout) {
pci_warn(dev, "not ready %dms after %s; giving up\n",
delay - 1, reset_type);
return -ENOTTY;
}

if (delay > PCI_RESET_WAIT)
if (delay > PCI_RESET_WAIT) {
if (retrain) {
retrain = false;
if (pcie_failed_link_retrain(bridge)) {
delay = 1;
continue;
}
}
pci_info(dev, "not ready %dms after %s; waiting\n",
delay - 1, reset_type);
}

msleep(delay);
delay *= 2;
pci_read_config_dword(dev, PCI_COMMAND, &id);
}

if (delay > PCI_RESET_WAIT)
Expand Down

0 comments on commit 08e3ed1

Please sign in to comment.