summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2016-09-18 05:39:20 +0200
committerBjorn Helgaas <bhelgaas@google.com>2016-09-28 18:46:51 +0200
commitcc7cc02bada84f0d707aa5b6d2ef8728a2e1f911 (patch)
treef1d963b141e5d6fae283afa49e4841faeeedb6e8 /drivers/pci/pci.c
parentPCI: Afford direct-complete to devices with non-standard PM (diff)
downloadlinux-cc7cc02bada84f0d707aa5b6d2ef8728a2e1f911.tar.xz
linux-cc7cc02bada84f0d707aa5b6d2ef8728a2e1f911.zip
PCI: Query platform firmware for device power state
Usually the most accurate way to determine a PCI device's power state is to read its PM Control & Status Register. There are two cases however when this is not an option: If the device doesn't have the PM capability at all, or if it is in D3cold (in which case its config space is inaccessible). In both cases, we can alternatively query the platform firmware for its opinion on the device's power state. To facilitate this, augment struct pci_platform_pm_ops with a ->get_power callback and implement it for acpi_pci_platform_pm (the only pci_platform_pm_ops existing so far). It is used by a forthcoming commit to let pci_update_current_state() recognize D3cold. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2f818c3e6571..2e18e9adcc15 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -552,8 +552,9 @@ static const struct pci_platform_pm_ops *pci_platform_pm;
int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
{
- if (!ops->is_manageable || !ops->set_state || !ops->choose_state ||
- !ops->sleep_wake || !ops->run_wake || !ops->need_resume)
+ if (!ops->is_manageable || !ops->set_state || !ops->get_state ||
+ !ops->choose_state || !ops->sleep_wake || !ops->run_wake ||
+ !ops->need_resume)
return -EINVAL;
pci_platform_pm = ops;
return 0;
@@ -570,6 +571,11 @@ static inline int platform_pci_set_power_state(struct pci_dev *dev,
return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS;
}
+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 pci_power_t platform_pci_choose_state(struct pci_dev *dev)
{
return pci_platform_pm ?