1
0
Fork 0

PCI / PM: Resume runtime-suspended devices later during system suspend

Runtime-suspended devices are resumed during system suspend by
pci_pm_prepare() for two reasons: First, because they may need
to be reprogrammed in order to change their wakeup settings and,
second, because they may need to be operatonal for their children
to be successfully suspended.  That is a problem, though, if there
are many runtime-suspended devices that need to be resumed this
way during system suspend, because the .prepare() PM callbacks of
devices are executed sequentially and the times taken by them
accumulate, which may increase the total system suspend time quite
a bit.

For this reason, move the resume of runtime-suspended devices up
to the next phase of device suspend (during system suspend), except
for the ones that have power.ignore_children set.  The exception is
made, because the devices with power.ignore_children set may still
be necessary for their children to be successfully suspended (during
system suspend) and they won't be resumed automatically as a result
of the runtime resume of their children.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
hifive-unleashed-5.1
Rafael J. Wysocki 2014-02-26 01:00:30 +01:00
parent 92858c476e
commit 7cd0602d78
1 changed files with 25 additions and 8 deletions

View File

@ -616,15 +616,11 @@ static int pci_pm_prepare(struct device *dev)
int error = 0;
/*
* PCI devices suspended at run time need to be resumed at this
* point, because in general it is necessary to reconfigure them for
* system suspend. Namely, if the device is supposed to wake up the
* system from the sleep state, we may need to reconfigure it for this
* purpose. In turn, if the device is not supposed to wake up the
* system from the sleep state, we'll have to prevent it from signaling
* wake-up.
* Devices having power.ignore_children set may still be necessary for
* suspending their children in the next phase of device suspend.
*/
pm_runtime_resume(dev);
if (dev->power.ignore_children)
pm_runtime_resume(dev);
if (drv && drv->pm && drv->pm->prepare)
error = drv->pm->prepare(dev);
@ -654,6 +650,16 @@ static int pci_pm_suspend(struct device *dev)
goto Fixup;
}
/*
* PCI devices suspended at run time need to be resumed at this point,
* because in general it is necessary to reconfigure them for system
* suspend. Namely, if the device is supposed to wake up the system
* from the sleep state, we may need to reconfigure it for this purpose.
* In turn, if the device is not supposed to wake up the system from the
* sleep state, we'll have to prevent it from signaling wake-up.
*/
pm_runtime_resume(dev);
pci_dev->state_saved = false;
if (pm->suspend) {
pci_power_t prev = pci_dev->current_state;
@ -808,6 +814,14 @@ static int pci_pm_freeze(struct device *dev)
return 0;
}
/*
* This used to be done in pci_pm_prepare() for all devices and some
* drivers may depend on it, so do it here. Ideally, runtime-suspended
* devices should not be touched during freeze/thaw transitions,
* however.
*/
pm_runtime_resume(dev);
pci_dev->state_saved = false;
if (pm->freeze) {
int error;
@ -915,6 +929,9 @@ static int pci_pm_poweroff(struct device *dev)
goto Fixup;
}
/* The reason to do that is the same as in pci_pm_suspend(). */
pm_runtime_resume(dev);
pci_dev->state_saved = false;
if (pm->poweroff) {
int error;