aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-29 19:10:24 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-10-12 16:29:57 -0400
commit2cef548adf58e9a58a411948b98edb9a3980dbe6 (patch)
tree7b74bbee5ce870e8a25751f95f059be777b8d555 /drivers/pci/pci-driver.c
parent25cb62b76430a91cc6195f902e61c2cb84ade622 (diff)
PCI / PM: Avoid resuming more devices during system suspend
Commit bac2a909a096 (PCI / PM: Avoid resuming PCI devices during system suspend) introduced a mechanism by which some PCI devices that were runtime-suspended at the system suspend time might be left in that state for the duration of the system suspend-resume cycle. However, it overlooked devices that were marked as capable of waking up the system just because PME support was detected in their PCI config space. Namely, in that case, device_can_wakeup(dev) returns 'true' for the device and if the device is not configured for system wakeup, device_may_wakeup(dev) returns 'false' and it will be resumed during system suspend even though configuring it for system wakeup may not really make sense at all. To avoid this problem, simply disable PME for PCI devices that have not been configured for system wakeup and are runtime-suspended at the system suspend time for the duration of the suspend-resume cycle. If the device is in D3cold, its config space is not available and it shouldn't be written to, but that's only possible if the device has platform PM support and the platform code is responsible for checking whether or not the device's configuration is suitable for system suspend in that case. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 108a3118ace7..8dfb144b8ccf 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -684,10 +684,21 @@ static int pci_pm_prepare(struct device *dev)
684 return pci_dev_keep_suspended(to_pci_dev(dev)); 684 return pci_dev_keep_suspended(to_pci_dev(dev));
685} 685}
686 686
687static void pci_pm_complete(struct device *dev)
688{
689 struct device_driver *drv = dev->driver;
690 struct pci_dev *pci_dev = to_pci_dev(dev);
691
692 pci_dev_complete_resume(pci_dev);
693
694 if (drv && drv->pm && drv->pm->complete)
695 drv->pm->complete(dev);
696}
687 697
688#else /* !CONFIG_PM_SLEEP */ 698#else /* !CONFIG_PM_SLEEP */
689 699
690#define pci_pm_prepare NULL 700#define pci_pm_prepare NULL
701#define pci_pm_complete NULL
691 702
692#endif /* !CONFIG_PM_SLEEP */ 703#endif /* !CONFIG_PM_SLEEP */
693 704
@@ -1218,6 +1229,7 @@ static int pci_pm_runtime_idle(struct device *dev)
1218 1229
1219static const struct dev_pm_ops pci_dev_pm_ops = { 1230static const struct dev_pm_ops pci_dev_pm_ops = {
1220 .prepare = pci_pm_prepare, 1231 .prepare = pci_pm_prepare,
1232 .complete = pci_pm_complete,
1221 .suspend = pci_pm_suspend, 1233 .suspend = pci_pm_suspend,
1222 .resume = pci_pm_resume, 1234 .resume = pci_pm_resume,
1223 .freeze = pci_pm_freeze, 1235 .freeze = pci_pm_freeze,