PCI PM: Run-time callbacks for PCI bus type

Introduce run-time PM callbacks for the PCI bus type.  Make the new
callbacks work in analogy with the existing system sleep PM
callbacks, so that the drivers already converted to struct dev_pm_ops
can use their suspend and resume routines for run-time PM without
modifications.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
Rafael J. Wysocki
2010-02-17 23:44:58 +01:00
committed by Jesse Barnes
parent 552be54cc4
commit 6cbf82148f
5 changed files with 184 additions and 34 deletions

View File

@ -1302,9 +1302,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
}
/**
* pci_enable_wake - enable PCI device as wakeup event source
* __pci_enable_wake - enable PCI device as wakeup event source
* @dev: PCI device affected
* @state: PCI state from which device will issue wakeup events
* @runtime: True if the events are to be generated at run time
* @enable: True to enable event generation; false to disable
*
* This enables the device as a wakeup event source, or disables it.
@ -1320,11 +1321,12 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
* Error code depending on the platform is returned if both the platform and
* the native mechanism fail to enable the generation of wake-up events
*/
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
bool runtime, bool enable)
{
int ret = 0;
if (enable && !device_may_wakeup(&dev->dev))
if (enable && !runtime && !device_may_wakeup(&dev->dev))
return -EINVAL;
/* Don't do the same thing twice in a row for one device. */
@ -1344,19 +1346,24 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
pci_pme_active(dev, true);
else
ret = 1;
error = platform_pci_sleep_wake(dev, true);
error = runtime ? platform_pci_run_wake(dev, true) :
platform_pci_sleep_wake(dev, true);
if (ret)
ret = error;
if (!ret)
dev->wakeup_prepared = true;
} else {
platform_pci_sleep_wake(dev, false);
if (runtime)
platform_pci_run_wake(dev, false);
else
platform_pci_sleep_wake(dev, false);
pci_pme_active(dev, false);
dev->wakeup_prepared = false;
}
return ret;
}
EXPORT_SYMBOL(__pci_enable_wake);
/**
* pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
@ -1465,6 +1472,31 @@ int pci_back_from_sleep(struct pci_dev *dev)
return pci_set_power_state(dev, PCI_D0);
}
/**
* pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend.
* @dev: PCI device being suspended.
*
* Prepare @dev to generate wake-up events at run time and put it into a low
* power state.
*/
int pci_finish_runtime_suspend(struct pci_dev *dev)
{
pci_power_t target_state = pci_target_state(dev);
int error;
if (target_state == PCI_POWER_ERROR)
return -EIO;
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
error = pci_set_power_state(dev, target_state);
if (error)
__pci_enable_wake(dev, target_state, true, false);
return error;
}
/**
* pci_dev_run_wake - Check if device can generate run-time wake-up events.
* @dev: Device to check.
@ -2978,7 +3010,6 @@ EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
EXPORT_SYMBOL(pci_pme_capable);
EXPORT_SYMBOL(pci_pme_active);
EXPORT_SYMBOL(pci_enable_wake);
EXPORT_SYMBOL(pci_wake_from_d3);
EXPORT_SYMBOL(pci_target_state);
EXPORT_SYMBOL(pci_prepare_to_sleep);