aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/pci/pci-driver.c12
-rw-r--r--drivers/pci/pci.c70
-rw-r--r--drivers/pci/pci.h1
3 files changed, 72 insertions, 11 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,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6a9a1116f1eb..78693fc5dbe9 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1710,15 +1710,7 @@ static void pci_pme_list_scan(struct work_struct *work)
1710 mutex_unlock(&pci_pme_list_mutex); 1710 mutex_unlock(&pci_pme_list_mutex);
1711} 1711}
1712 1712
1713/** 1713static void __pci_pme_active(struct pci_dev *dev, bool enable)
1714 * pci_pme_active - enable or disable PCI device's PME# function
1715 * @dev: PCI device to handle.
1716 * @enable: 'true' to enable PME# generation; 'false' to disable it.
1717 *
1718 * The caller must verify that the device is capable of generating PME# before
1719 * calling this function with @enable equal to 'true'.
1720 */
1721void pci_pme_active(struct pci_dev *dev, bool enable)
1722{ 1714{
1723 u16 pmcsr; 1715 u16 pmcsr;
1724 1716
@@ -1732,6 +1724,19 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
1732 pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; 1724 pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
1733 1725
1734 pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); 1726 pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
1727}
1728
1729/**
1730 * pci_pme_active - enable or disable PCI device's PME# function
1731 * @dev: PCI device to handle.
1732 * @enable: 'true' to enable PME# generation; 'false' to disable it.
1733 *
1734 * The caller must verify that the device is capable of generating PME# before
1735 * calling this function with @enable equal to 'true'.
1736 */
1737void pci_pme_active(struct pci_dev *dev, bool enable)
1738{
1739 __pci_pme_active(dev, enable);
1735 1740
1736 /* 1741 /*
1737 * PCI (as opposed to PCIe) PME requires that the device have 1742 * PCI (as opposed to PCIe) PME requires that the device have
@@ -2032,17 +2037,60 @@ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
2032 * reconfigured due to wakeup settings difference between system and runtime 2037 * reconfigured due to wakeup settings difference between system and runtime
2033 * suspend and the current power state of it is suitable for the upcoming 2038 * suspend and the current power state of it is suitable for the upcoming
2034 * (system) transition. 2039 * (system) transition.
2040 *
2041 * If the device is not configured for system wakeup, disable PME for it before
2042 * returning 'true' to prevent it from waking up the system unnecessarily.
2035 */ 2043 */
2036bool pci_dev_keep_suspended(struct pci_dev *pci_dev) 2044bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
2037{ 2045{
2038 struct device *dev = &pci_dev->dev; 2046 struct device *dev = &pci_dev->dev;
2039 2047
2040 if (!pm_runtime_suspended(dev) 2048 if (!pm_runtime_suspended(dev)
2041 || (device_can_wakeup(dev) && !device_may_wakeup(dev)) 2049 || pci_target_state(pci_dev) != pci_dev->current_state
2042 || platform_pci_need_resume(pci_dev)) 2050 || platform_pci_need_resume(pci_dev))
2043 return false; 2051 return false;
2044 2052
2045 return pci_target_state(pci_dev) == pci_dev->current_state; 2053 /*
2054 * At this point the device is good to go unless it's been configured
2055 * to generate PME at the runtime suspend time, but it is not supposed
2056 * to wake up the system. In that case, simply disable PME for it
2057 * (it will have to be re-enabled on exit from system resume).
2058 *
2059 * If the device's power state is D3cold and the platform check above
2060 * hasn't triggered, the device's configuration is suitable and we don't
2061 * need to manipulate it at all.
2062 */
2063 spin_lock_irq(&dev->power.lock);
2064
2065 if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold &&
2066 !device_may_wakeup(dev))
2067 __pci_pme_active(pci_dev, false);
2068
2069 spin_unlock_irq(&dev->power.lock);
2070 return true;
2071}
2072
2073/**
2074 * pci_dev_complete_resume - Finalize resume from system sleep for a device.
2075 * @pci_dev: Device to handle.
2076 *
2077 * If the device is runtime suspended and wakeup-capable, enable PME for it as
2078 * it might have been disabled during the prepare phase of system suspend if
2079 * the device was not configured for system wakeup.
2080 */
2081void pci_dev_complete_resume(struct pci_dev *pci_dev)
2082{
2083 struct device *dev = &pci_dev->dev;
2084
2085 if (!pci_dev_run_wake(pci_dev))
2086 return;
2087
2088 spin_lock_irq(&dev->power.lock);
2089
2090 if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold)
2091 __pci_pme_active(pci_dev, true);
2092
2093 spin_unlock_irq(&dev->power.lock);
2046} 2094}
2047 2095
2048void pci_config_pm_runtime_get(struct pci_dev *pdev) 2096void pci_config_pm_runtime_get(struct pci_dev *pdev)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 24ba9dc8910a..037e787a3ad5 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -75,6 +75,7 @@ void pci_disable_enabled_device(struct pci_dev *dev);
75int pci_finish_runtime_suspend(struct pci_dev *dev); 75int pci_finish_runtime_suspend(struct pci_dev *dev);
76int __pci_pme_wakeup(struct pci_dev *dev, void *ign); 76int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
77bool pci_dev_keep_suspended(struct pci_dev *dev); 77bool pci_dev_keep_suspended(struct pci_dev *dev);
78void pci_dev_complete_resume(struct pci_dev *pci_dev);
78void pci_config_pm_runtime_get(struct pci_dev *dev); 79void pci_config_pm_runtime_get(struct pci_dev *dev);
79void pci_config_pm_runtime_put(struct pci_dev *dev); 80void pci_config_pm_runtime_put(struct pci_dev *dev);
80void pci_pm_init(struct pci_dev *dev); 81void pci_pm_init(struct pci_dev *dev);