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>
This commit is contained in:
parent
9a6058312e
commit
730643d33e
@ -564,6 +564,17 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
|
|||||||
pci_pme_restore(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 */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
@ -939,7 +950,7 @@ static int pci_pm_resume_noirq(struct device *dev)
|
|||||||
pcie_pme_root_status_cleanup(pci_dev);
|
pcie_pme_root_status_cleanup(pci_dev);
|
||||||
|
|
||||||
if (!skip_bus_pm && prev_state == PCI_D3cold)
|
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))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1326,7 +1337,7 @@ static int pci_pm_runtime_resume(struct device *dev)
|
|||||||
pci_pm_default_resume(pci_dev);
|
pci_pm_default_resume(pci_dev);
|
||||||
|
|
||||||
if (prev_state == PCI_D3cold)
|
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)
|
if (pm && pm->runtime_resume)
|
||||||
error = pm->runtime_resume(dev);
|
error = pm->runtime_resume(dev);
|
||||||
|
@ -1310,21 +1310,6 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
|
|||||||
int pci_power_up(struct pci_dev *dev)
|
int pci_power_up(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
pci_platform_power_transition(dev, PCI_D0);
|
pci_platform_power_transition(dev, PCI_D0);
|
||||||
|
|
||||||
/*
|
|
||||||
* Mandatory power management transition delays are handled in
|
|
||||||
* pci_pm_resume_noirq() and pci_pm_runtime_resume() of the
|
|
||||||
* corresponding bridge.
|
|
||||||
*/
|
|
||||||
if (dev->runtime_d3cold) {
|
|
||||||
/*
|
|
||||||
* 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(dev->subordinate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pci_raw_set_power_state(dev, PCI_D0);
|
return pci_raw_set_power_state(dev, PCI_D0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user