--- drivers/pci/pci-driver.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -555,11 +555,16 @@ static void pci_pm_default_resume(struct pci_enable_wake(pci_dev, PCI_D0, false); } -static void pci_pm_default_resume_early(struct pci_dev *pci_dev) +static int pci_pm_default_resume_early(struct pci_dev *pci_dev) { pci_pm_power_up_and_verify_state(pci_dev); + /* Bail out if the device is not accessible. */ + if (pci_dev->current_state == PCI_D3cold) + return -ENODEV; + pci_restore_state(pci_dev); pci_pme_restore(pci_dev); + return 0; } static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) @@ -958,8 +963,11 @@ static int pci_pm_resume_noirq(struct de * configuration here and attempting to put them into D0 again is * pointless, so avoid doing that. */ - if (!(skip_bus_pm && pm_suspend_no_platform())) - pci_pm_default_resume_early(pci_dev); + if (!(skip_bus_pm && pm_suspend_no_platform())) { + int error = pci_pm_default_resume_early(pci_dev); + if (error) + return error; + } pci_fixup_device(pci_fixup_resume_early, pci_dev); pcie_pme_root_status_cleanup(pci_dev); @@ -1221,8 +1229,12 @@ static int pci_pm_restore_noirq(struct d { struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + int error; + + error = pci_pm_default_resume_early(pci_dev); + if (error) + return error; - pci_pm_default_resume_early(pci_dev); pci_fixup_device(pci_fixup_resume_early, pci_dev); if (pci_has_legacy_pm_support(pci_dev)) @@ -1339,14 +1351,17 @@ static int pci_pm_runtime_resume(struct struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; pci_power_t prev_state = pci_dev->current_state; - int error = 0; + int error; /* * Restoring config space is necessary even if the device is not bound * to a driver because although we left it in D0, it may have gone to * D3cold when the bridge above it runtime suspended. */ - pci_pm_default_resume_early(pci_dev); + error = pci_pm_default_resume_early(pci_dev); + if (error) + return error; + pci_resume_ptm(pci_dev); if (!pci_dev->driver)