From: Stanislav Spassov <stanspas@xxxxxxxxx> This patch does not (intentionally) introduce any observable difference in runtime behavior. Signed-off-by: Stanislav Spassov <stanspas@xxxxxxxxx> --- drivers/pci/pci.c | 70 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d828ca835a98..44f5d4907db6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1021,47 +1021,75 @@ 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) +/* + * Performs DWORD Configuration Reads at a specific offset until the value read + * (with mask applied) is not equal to bad_value. + */ +static inline int pci_dev_poll_until_not_equal(struct pci_dev *dev, int where, + u32 mask, u32 bad_value, + const char *event_name, + int timeout, int *waited, + u32 *final_value) { int delay = 1; - u32 id; + u32 value; - /* - * After reset, the device should not silently discard config - * requests, but it may still indicate that it needs more time by - * responding to them with CRS completions. The Root Port will - * generally synthesize ~0 data to complete the read (except when - * CRS SV is enabled and the read was for the Vendor ID; in that - * case it synthesizes 0x0001 data). - * - * Wait for the device to return a non-CRS completion. Read the - * 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 (id == ~0) { + if (!event_name) + event_name = "<unknown event>"; + + if (waited) + delay = *waited + 1; + + pci_read_config_dword(dev, where, &value); + + while ((value & mask) == bad_value) { if (delay > timeout) { pci_warn(dev, "not ready %dms after %s; giving up\n", - delay - 1, reset_type); + delay - 1, event_name); return -ENOTTY; } if (delay > 1000) pci_info(dev, "not ready %dms after %s; waiting\n", - delay - 1, reset_type); + delay - 1, event_name); msleep(delay); delay *= 2; - pci_read_config_dword(dev, PCI_COMMAND, &id); + + pci_read_config_dword(dev, where, &value); } if (delay > 1000) - pci_info(dev, "ready %dms after %s\n", delay - 1, - reset_type); + pci_info(dev, "ready %dms after %s\n", delay - 1, event_name); + + if (waited) + *waited = delay - 1; + + if (final_value) + *final_value = value; return 0; } +static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) +{ + /* + * After reset, the device should not silently discard config + * requests, but it may still indicate that it needs more time by + * responding to them with CRS completions. The Root Port will + * generally synthesize ~0 data to complete the read (except when + * CRS SV is enabled and the read was for the Vendor ID; in that + * case it synthesizes 0x0001 data). + * + * Wait for the device to return a non-CRS completion. Read the + * Command register instead of Vendor ID so we don't have to + * contend with the CRS SV value. + */ + return pci_dev_poll_until_not_equal(dev, PCI_COMMAND, ~0, ~0, + reset_type, timeout, NULL, + NULL); +} + /** * pci_power_up - Put the given device into D0 * @dev: PCI device to power up -- 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