From: Stanislav Spassov <stanspas@xxxxxxxxx> A broken device may never become responsive after reset, hence the need for a timeout. However, waiting for too long can have unintended side effects such as triggering hung task timeouts for processes waiting on a lock held during the reset. Locks that are shared across multiple devices, such as VFIO's per-bus reflck, are especially problematic, because a single broken VF can cause hangs for processes working with other VFs on the same bus. To allow lowering the global default post-reset timeout, while still accommodating devices that require more time, this patch introduces a per-device override that can be configured via a quirk. Signed-off-by: Stanislav Spassov <stanspas@xxxxxxxxx> --- drivers/pci/pci.c | 19 ++++++++++++++----- drivers/pci/probe.c | 2 ++ include/linux/pci.h | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index db9b58ab6c68..a554818968ed 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1033,8 +1033,17 @@ void pci_wakeup_bus(struct pci_bus *bus) pci_walk_bus(bus, pci_wakeup, NULL); } -static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) +static int pci_dev_get_reset_ready_poll_ms(struct pci_dev *dev) { + if (dev->reset_ready_poll_ms >= 0) + return dev->reset_ready_poll_ms; + + return pcie_reset_ready_poll_ms; +} + +static int pci_dev_wait(struct pci_dev *dev, char *reset_type) +{ + int timeout = pci_dev_get_reset_ready_poll_ms(dev); int delay = 1; u32 id; @@ -4518,7 +4527,7 @@ int pcie_flr(struct pci_dev *dev) */ msleep(100); - return pci_dev_wait(dev, "FLR", pcie_reset_ready_poll_ms); + return pci_dev_wait(dev, "FLR"); } EXPORT_SYMBOL_GPL(pcie_flr); @@ -4563,7 +4572,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe) */ msleep(100); - return pci_dev_wait(dev, "AF_FLR", pcie_reset_ready_poll_ms); + return pci_dev_wait(dev, "AF_FLR"); } /** @@ -4608,7 +4617,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); pci_dev_d3_sleep(dev); - return pci_dev_wait(dev, "PM D3hot->D0", pcie_reset_ready_poll_ms); + return pci_dev_wait(dev, "PM D3hot->D0"); } /** @@ -4838,7 +4847,7 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { pcibios_reset_secondary_bus(dev); - return pci_dev_wait(dev, "bus reset", pcie_reset_ready_poll_ms); + return pci_dev_wait(dev, "bus reset"); } EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 512cb4312ddd..eeb79a45d504 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2166,6 +2166,8 @@ struct pci_dev *pci_alloc_dev(struct pci_bus *bus) if (!dev) return NULL; + dev->reset_ready_poll_ms = -1; + INIT_LIST_HEAD(&dev->bus_list); dev->dev.type = &pci_dev_type; dev->bus = pci_bus_get(bus); diff --git a/include/linux/pci.h b/include/linux/pci.h index 3840a541a9de..049a41b9412b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -468,6 +468,7 @@ struct pci_dev { size_t romlen; /* Length if not from BAR */ char *driver_override; /* Driver name to force a match */ + int reset_ready_poll_ms; unsigned long priv_flags; /* Private flags for the PCI driver */ }; -- 2.25.1 Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879