aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2012-06-22 22:23:51 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-23 12:50:59 -0400
commit448bd857d48e69b33ef323739dc6d8ca20d4cda7 (patch)
tree4c1178f9c7dd2d78af2ac1ed26b214b04be1554a /drivers/pci/pci-driver.c
parent8497f696686ae1ab3f01e5956046d59844b9f500 (diff)
PCI/PM: add PCIe runtime D3cold support
This patch adds runtime D3cold support and corresponding ACPI platform support. This patch only enables runtime D3cold support; it does not enable D3cold support during system suspend/hibernate. D3cold is the deepest power saving state for a PCIe device, where its main power is removed. While it is in D3cold, you can't access the device at all, not even its configuration space (which is still accessible in D3hot). Therefore the PCI PM registers can not be used to transition into/out of the D3cold state; that must be done by platform logic such as ACPI _PR3. To support wakeup from D3cold, a system may provide auxiliary power, which allows a device to request wakeup using a Beacon or the sideband WAKE# signal. WAKE# is usually connected to platform logic such as ACPI GPE. This is quite different from other power saving states, where devices request wakeup via a PME message on the PCIe link. Some devices, such as those in plug-in slots, have no direct platform logic. For example, there is usually no ACPI _PR3 for them. D3cold support for these devices can be done via the PCIe Downstream Port leading to the device. When the PCIe port is powered on/off, the device is powered on/off too. Wakeup events from the device will be notified to the corresponding PCIe port. For more information about PCIe D3cold and corresponding ACPI support, please refer to: - PCI Express Base Specification Revision 2.0 - Advanced Configuration and Power Interface Specification Revision 5.0 [bhelgaas: changelog] Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl> Originally-by: Zheng Yan <zheng.z.yan@intel.com> Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index bf0cee629b60..ca2e4c79a588 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -1019,10 +1019,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
1019 if (!pm || !pm->runtime_suspend) 1019 if (!pm || !pm->runtime_suspend)
1020 return -ENOSYS; 1020 return -ENOSYS;
1021 1021
1022 pci_dev->no_d3cold = false;
1022 error = pm->runtime_suspend(dev); 1023 error = pm->runtime_suspend(dev);
1023 suspend_report_result(pm->runtime_suspend, error); 1024 suspend_report_result(pm->runtime_suspend, error);
1024 if (error) 1025 if (error)
1025 return error; 1026 return error;
1027 if (!pci_dev->d3cold_allowed)
1028 pci_dev->no_d3cold = true;
1026 1029
1027 pci_fixup_device(pci_fixup_suspend, pci_dev); 1030 pci_fixup_device(pci_fixup_suspend, pci_dev);
1028 1031
@@ -1044,6 +1047,7 @@ static int pci_pm_runtime_suspend(struct device *dev)
1044 1047
1045static int pci_pm_runtime_resume(struct device *dev) 1048static int pci_pm_runtime_resume(struct device *dev)
1046{ 1049{
1050 int rc;
1047 struct pci_dev *pci_dev = to_pci_dev(dev); 1051 struct pci_dev *pci_dev = to_pci_dev(dev);
1048 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 1052 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
1049 1053
@@ -1054,7 +1058,11 @@ static int pci_pm_runtime_resume(struct device *dev)
1054 __pci_enable_wake(pci_dev, PCI_D0, true, false); 1058 __pci_enable_wake(pci_dev, PCI_D0, true, false);
1055 pci_fixup_device(pci_fixup_resume, pci_dev); 1059 pci_fixup_device(pci_fixup_resume, pci_dev);
1056 1060
1057 return pm->runtime_resume(dev); 1061 rc = pm->runtime_resume(dev);
1062
1063 pci_dev->runtime_d3cold = false;
1064
1065 return rc;
1058} 1066}
1059 1067
1060static int pci_pm_runtime_idle(struct device *dev) 1068static int pci_pm_runtime_idle(struct device *dev)