summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-06-25 14:09:12 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-06-27 12:33:26 +0200
commitb51033e06c2ebbad322370f4a35c84488e61b342 (patch)
tree3ac6b898f1cba06f50b1f7f636ca0f848c9236e6 /drivers/pci/pci.c
parent53b22f900c2d282bf6499712930188cc02306e4e (diff)
downloadlwn-b51033e06c2ebbad322370f4a35c84488e61b342.tar.gz
lwn-b51033e06c2ebbad322370f4a35c84488e61b342.zip
PCI: PM/ACPI: Refresh all stale power state data in pci_pm_complete()
In pci_pm_complete() there are checks to decide whether or not to resume devices that were left in runtime-suspend during the preceding system-wide transition into a sleep state. They involve checking the current power state of the device and comparing it with the power state of it set before the preceding system-wide transition, but the platform component of the device's power state is not handled correctly in there. Namely, on platforms with ACPI, the device power state information needs to be updated with care, so that the reference counters of power resources used by the device (if any) are set to ensure that the refreshed power state of it will be maintained going forward. To that end, introduce a new ->refresh_state() platform PM callback for PCI devices, for asking the platform to refresh the device power state data and ensure that the corresponding power state will be maintained going forward, make it invoke acpi_device_update_power() (for devices with ACPI PM) on platforms with ACPI and make pci_pm_complete() use it, through a new pci_refresh_power_state() wrapper function. Fixes: a0d2a959d3da (PCI: Avoid unnecessary resume after direct-complete) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e34fb2b3c466..b1f563916036 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -777,6 +777,12 @@ static inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev)
return pci_platform_pm ? pci_platform_pm->get_state(dev) : PCI_UNKNOWN;
}
+static inline void platform_pci_refresh_power_state(struct pci_dev *dev)
+{
+ if (pci_platform_pm && pci_platform_pm->refresh_state)
+ pci_platform_pm->refresh_state(dev);
+}
+
static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
{
return pci_platform_pm ?
@@ -938,6 +944,21 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
}
/**
+ * pci_refresh_power_state - Refresh the given device's power state data
+ * @dev: Target PCI device.
+ *
+ * Ask the platform to refresh the devices power state information and invoke
+ * pci_update_current_state() to update its current PCI power state.
+ */
+void pci_refresh_power_state(struct pci_dev *dev)
+{
+ if (platform_pci_power_manageable(dev))
+ platform_pci_refresh_power_state(dev);
+
+ pci_update_current_state(dev, dev->current_state);
+}
+
+/**
* pci_power_up - Put the given device into D0 forcibly
* @dev: PCI device to power up
*/