From: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> There is an arbitrary difference between the system resume and runtime resume code paths for PCI devices regarding the delay to apply when switching the devices from D3cold to D0. Namely, pci_restore_standard_config() used in the runtime resume code path calls pci_set_power_state() which in turn invokes __pci_start_power_transition() to power up the device through the platform firmware and that function applies the transition delay (as per PCI Express Base Specification Revision 2.0, Section 6.6.1). However, pci_pm_default_resume_early() used in the system resume code path calls pci_power_up() which doesn't apply the delay at all and that causes issues to occur during resume from suspend-to-idle on some systems where the delay is required. Since there is no reason for that difference to exist, modify pci_pm_default_resume_early() to invoke pci_restore_standard_config() instead of pci_power_up() and drop the latter, but in order to prevent the ACPI power state values (cached by the ACPI layer) from becoming stale in some cases during resume from suspend-to-RAM (ACPI S3), as per commit cc2893b6af52 ("PCI: Ensure we re-enable devices on resume"), refresh the ACPI power state information in pci_pm_default_resume_early() in that case. [Note that while this change should take the issue originally addressed by commit cc2893b6af52 ("PCI: Ensure we re-enable devices on resume") into account in a generally safer way, an alternative would be to make pci_power_up() use __pci_start_power_transition() instead of calling platform_pci_set_power_state() directly.] Fixes: db288c9c5f9d ("PCI / PM: restore the original behavior of pci_set_power_state()") Reported-by: Daniel Drake <drake@xxxxxxxxxxxx> Tested-by: Daniel Drake <drake@xxxxxxxxxxxx> Link: https://lore.kernel.org/linux-pm/CAD8Lp44TYxrMgPLkHCqF9hv6smEurMXvmmvmtyFhZ6Q4SE+dig@xxxxxxxxxxxxxx/T/#m21be74af263c6a34f36e0fc5c77c5449d9406925 Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> --- drivers/pci/pci-driver.c | 8 +++++--- drivers/pci/pci.c | 15 --------------- drivers/pci/pci.h | 1 - 3 files changed, 5 insertions(+), 19 deletions(-) Index: linux-pm/drivers/pci/pci-driver.c =================================================================== --- linux-pm.orig/drivers/pci/pci-driver.c +++ linux-pm/drivers/pci/pci-driver.c @@ -523,9 +523,10 @@ static int pci_restore_standard_config(s static void pci_pm_default_resume_early(struct pci_dev *pci_dev) { - pci_power_up(pci_dev); - pci_restore_state(pci_dev); - pci_pme_restore(pci_dev); + if (pm_resume_via_firmware()) + pci_refresh_power_state(pci_dev); + + pci_restore_standard_config(pci_dev); } /* @@ -713,6 +714,7 @@ static void pci_pm_complete(struct devic pci_power_t pre_sleep_state = pci_dev->current_state; pci_refresh_power_state(pci_dev); + pci_update_current_state(pci_dev, pci_dev->current_state); /* * On platforms with ACPI this check may also trigger for * devices sharing power resources if one of those power Index: linux-pm/drivers/pci/pci.c =================================================================== --- linux-pm.orig/drivers/pci/pci.c +++ linux-pm/drivers/pci/pci.c @@ -954,21 +954,6 @@ void pci_refresh_power_state(struct pci_ { if (platform_pci_power_manageable(dev)) platform_pci_refresh_power_state(dev); - - pci_update_current_state(dev, dev->current_state); -} - -/** - * pci_power_up - Put the given device into D0 forcibly - * @dev: PCI device to power up - */ -void pci_power_up(struct pci_dev *dev) -{ - if (platform_pci_power_manageable(dev)) - platform_pci_set_power_state(dev, PCI_D0); - - pci_raw_set_power_state(dev, PCI_D0); - pci_update_current_state(dev, PCI_D0); } /** Index: linux-pm/drivers/pci/pci.h =================================================================== --- linux-pm.orig/drivers/pci/pci.h +++ linux-pm/drivers/pci/pci.h @@ -85,7 +85,6 @@ struct pci_platform_pm_ops { int pci_set_platform_pm(const struct pci_platform_pm_ops *ops); void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_refresh_power_state(struct pci_dev *dev); -void pci_power_up(struct pci_dev *dev); void pci_disable_enabled_device(struct pci_dev *dev); int pci_finish_runtime_suspend(struct pci_dev *dev); void pcie_clear_root_pme_status(struct pci_dev *dev);