Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+25 -8
+25 -8
drivers/pci/pci-driver.c
··· 616 616 int error = 0; 617 617 618 618 /* 619 - * PCI devices suspended at run time need to be resumed at this 620 - * point, because in general it is necessary to reconfigure them for 621 - * system suspend. Namely, if the device is supposed to wake up the 622 - * system from the sleep state, we may need to reconfigure it for this 623 - * purpose. In turn, if the device is not supposed to wake up the 624 - * system from the sleep state, we'll have to prevent it from signaling 625 - * wake-up. 619 + * Devices having power.ignore_children set may still be necessary for 620 + * suspending their children in the next phase of device suspend. 626 621 */ 627 - pm_runtime_resume(dev); 622 + if (dev->power.ignore_children) 623 + pm_runtime_resume(dev); 628 624 629 625 if (drv && drv->pm && drv->pm->prepare) 630 626 error = drv->pm->prepare(dev); ··· 649 653 pci_pm_default_suspend(pci_dev); 650 654 goto Fixup; 651 655 } 656 + 657 + /* 658 + * PCI devices suspended at run time need to be resumed at this point, 659 + * because in general it is necessary to reconfigure them for system 660 + * suspend. Namely, if the device is supposed to wake up the system 661 + * from the sleep state, we may need to reconfigure it for this purpose. 662 + * In turn, if the device is not supposed to wake up the system from the 663 + * sleep state, we'll have to prevent it from signaling wake-up. 664 + */ 665 + pm_runtime_resume(dev); 652 666 653 667 pci_dev->state_saved = false; 654 668 if (pm->suspend) { ··· 814 808 return 0; 815 809 } 816 810 811 + /* 812 + * This used to be done in pci_pm_prepare() for all devices and some 813 + * drivers may depend on it, so do it here. Ideally, runtime-suspended 814 + * devices should not be touched during freeze/thaw transitions, 815 + * however. 816 + */ 817 + pm_runtime_resume(dev); 818 + 817 819 pci_dev->state_saved = false; 818 820 if (pm->freeze) { 819 821 int error; ··· 928 914 pci_pm_default_suspend(pci_dev); 929 915 goto Fixup; 930 916 } 917 + 918 + /* The reason to do that is the same as in pci_pm_suspend(). */ 919 + pm_runtime_resume(dev); 931 920 932 921 pci_dev->state_saved = false; 933 922 if (pm->poweroff) {