summaryrefslogtreecommitdiff
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2022-04-14 15:04:13 +0200
committerBjorn Helgaas <bhelgaas@google.com>2022-05-05 14:19:45 -0500
commit730643d33e2d9ae52d974201b5017d8c3efe5aa5 (patch)
tree4cbdeb14ca16e84f72b275cfad25ca745e67cfc8 /drivers/pci/pci-driver.c
parent9a6058312ea941bac3b0ba8c963d7543fc42a288 (diff)
PCI/PM: Resume subordinate bus in bus type callbacks
Calling pci_resume_bus() on the secondary bus from pci_power_up() as it is done now is questionable, because it depends on the mandatory bridge power-up delays that are only covered by the PCI bus type PM callbacks. For this reason, move the subordinate bus resume to those callbacks too and use the observation that if a bridge is being powered-up during resume from system-wide suspend, it may be still desirable to runtime-resume its subordinate bus after completing the system-wide transition (in case the resume of the devices on that bus is skipped during it). Link: https://lore.kernel.org/r/3190097.aeNJFYEL58@kreacher Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 608ce87d0d48..ee5868810a5b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -564,6 +564,17 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
pci_pme_restore(pci_dev);
}
+static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev)
+{
+ pci_bridge_wait_for_secondary_bus(pci_dev);
+ /*
+ * When powering on a bridge from D3cold, the whole hierarchy may be
+ * powered on into D0uninitialized state, resume them to give them a
+ * chance to suspend again
+ */
+ pci_resume_bus(pci_dev->subordinate);
+}
+
#endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP
@@ -939,7 +950,7 @@ static int pci_pm_resume_noirq(struct device *dev)
pcie_pme_root_status_cleanup(pci_dev);
if (!skip_bus_pm && prev_state == PCI_D3cold)
- pci_bridge_wait_for_secondary_bus(pci_dev);
+ pci_pm_bridge_power_up_actions(pci_dev);
if (pci_has_legacy_pm_support(pci_dev))
return 0;
@@ -1326,7 +1337,7 @@ static int pci_pm_runtime_resume(struct device *dev)
pci_pm_default_resume(pci_dev);
if (prev_state == PCI_D3cold)
- pci_bridge_wait_for_secondary_bus(pci_dev);
+ pci_pm_bridge_power_up_actions(pci_dev);
if (pm && pm->runtime_resume)
error = pm->runtime_resume(dev);