diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2012-11-26 13:00:57 -0700 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-11-26 13:00:57 -0700 |
commit | d3fe3988fb24e5ed13b2243b789a652882d3b26c (patch) | |
tree | 1257424a712583bf474cb0831621a47e73dfc3de /drivers/pci/pci.c | |
parent | 7db78a9c864d1baf916d849febef31e274cfcb1f (diff) | |
parent | ff8e59bc4ec3f31789a47dce9b6fe44bd7bc5fcc (diff) |
Merge branch 'for-linus' into next
* for-linus:
PCI/portdrv: Don't create hotplug slots unless port supports hotplug
PCI/PM: Fix proc config reg access for D3cold and bridge suspending
PCI/PM: Resume device before shutdown
PCI/PM: Fix deadlock when unbinding device if parent in D3cold
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 05a510d1bb3..adffc6f621e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1868,6 +1868,38 @@ bool pci_dev_run_wake(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_dev_run_wake); +void pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +void pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + /** * pci_pm_init - Initialize PM functions of given PCI device * @dev: PCI device to handle. |