summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6cdd7e641ca6..b9fecc25d213 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1561,6 +1561,7 @@ int pci_save_state(struct pci_dev *dev)
pci_save_aspm_l1ss_state(dev);
pci_save_dpc_state(dev);
pci_save_aer_state(dev);
+ pci_save_ptm_state(dev);
return pci_save_vc_state(dev);
}
EXPORT_SYMBOL(pci_save_state);
@@ -1673,6 +1674,7 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_vc_state(dev);
pci_restore_rebar_state(dev);
pci_restore_dpc_state(dev);
+ pci_restore_ptm_state(dev);
pci_aer_clear_status(dev);
pci_restore_aer_state(dev);
@@ -2602,12 +2604,24 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
if (target_state == PCI_POWER_ERROR)
return -EIO;
+ /*
+ * There are systems (for example, Intel mobile chips since Coffee
+ * Lake) where the power drawn while suspended can be significantly
+ * reduced by disabling PTM on PCIe root ports as this allows the
+ * port to enter a lower-power PM state and the SoC to reach a
+ * lower-power idle state as a whole.
+ */
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+ pci_disable_ptm(dev);
+
pci_enable_wake(dev, target_state, wakeup);
error = pci_set_power_state(dev, target_state);
- if (error)
+ if (error) {
pci_enable_wake(dev, target_state, false);
+ pci_restore_ptm_state(dev);
+ }
return error;
}
@@ -2645,12 +2659,23 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
dev->runtime_d3cold = target_state == PCI_D3cold;
+ /*
+ * There are systems (for example, Intel mobile chips since Coffee
+ * Lake) where the power drawn while suspended can be significantly
+ * reduced by disabling PTM on PCIe root ports as this allows the
+ * port to enter a lower-power PM state and the SoC to reach a
+ * lower-power idle state as a whole.
+ */
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+ pci_disable_ptm(dev);
+
__pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
error = pci_set_power_state(dev, target_state);
if (error) {
pci_enable_wake(dev, target_state, false);
+ pci_restore_ptm_state(dev);
dev->runtime_d3cold = false;
}