Skip to content

Commit 08e3ed1

Browse files
maciej-w-rozyckibjorn-helgaas
authored andcommitted
PCI: Add failed link recovery for device reset events
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/[email protected] Signed-off-by: Maciej W. Rozycki <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent a89c822 commit 08e3ed1

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

drivers/pci/pci.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,14 @@ void pci_resume_bus(struct pci_bus *bus)
11561156
static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
11571157
{
11581158
int delay = 1;
1159-
u32 id;
1159+
bool retrain = false;
1160+
struct pci_dev *bridge;
1161+
1162+
if (pci_is_pcie(dev)) {
1163+
bridge = pci_upstream_bridge(dev);
1164+
if (bridge)
1165+
retrain = true;
1166+
}
11601167

11611168
/*
11621169
* After reset, the device should not silently discard config
@@ -1170,21 +1177,33 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
11701177
* Command register instead of Vendor ID so we don't have to
11711178
* contend with the CRS SV value.
11721179
*/
1173-
pci_read_config_dword(dev, PCI_COMMAND, &id);
1174-
while (PCI_POSSIBLE_ERROR(id)) {
1180+
for (;;) {
1181+
u32 id;
1182+
1183+
pci_read_config_dword(dev, PCI_COMMAND, &id);
1184+
if (!PCI_POSSIBLE_ERROR(id))
1185+
break;
1186+
11751187
if (delay > timeout) {
11761188
pci_warn(dev, "not ready %dms after %s; giving up\n",
11771189
delay - 1, reset_type);
11781190
return -ENOTTY;
11791191
}
11801192

1181-
if (delay > PCI_RESET_WAIT)
1193+
if (delay > PCI_RESET_WAIT) {
1194+
if (retrain) {
1195+
retrain = false;
1196+
if (pcie_failed_link_retrain(bridge)) {
1197+
delay = 1;
1198+
continue;
1199+
}
1200+
}
11821201
pci_info(dev, "not ready %dms after %s; waiting\n",
11831202
delay - 1, reset_type);
1203+
}
11841204

11851205
msleep(delay);
11861206
delay *= 2;
1187-
pci_read_config_dword(dev, PCI_COMMAND, &id);
11881207
}
11891208

11901209
if (delay > PCI_RESET_WAIT)

0 commit comments

Comments
 (0)