Merge branch 'acpi-pm'
* acpi-pm: PM / core: Drop run_wake flag from struct dev_pm_info PCI / PM: Simplify device wakeup settings code PCI / PM: Drop pme_interrupt flag from struct pci_dev ACPI / PM: Consolidate device wakeup settings code ACPI / PM: Drop run_wake from struct acpi_device_wakeup_flags ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems platform: x86: intel-hid: Wake up the system from suspend-to-idle platform: x86: intel-vbtn: Wake up the system from suspend-to-idle ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle platform/x86: Add driver for ACPI INT0002 Virtual GPIO device PCI / PM: Restore PME Enable if skipping wakeup setup PM / sleep: Print timing information if debug is enabled ACPI / PM: Clean up device wakeup enable/disable code ACPI / PM: Change log level of wakeup-related message USB / PCI / PM: Allow the PCI core to do the resume cleanup ACPI / PM: Run wakeup notify handlers synchronously Conflicts: drivers/base/power/main.c
This commit is contained in:
@@ -394,29 +394,26 @@ bool pciehp_is_native(struct pci_dev *pdev)
|
||||
|
||||
/**
|
||||
* pci_acpi_wake_bus - Root bus wakeup notification fork function.
|
||||
* @work: Work item to handle.
|
||||
* @context: Device wakeup context.
|
||||
*/
|
||||
static void pci_acpi_wake_bus(struct work_struct *work)
|
||||
static void pci_acpi_wake_bus(struct acpi_device_wakeup_context *context)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct acpi_pci_root *root;
|
||||
|
||||
adev = container_of(work, struct acpi_device, wakeup.context.work);
|
||||
adev = container_of(context, struct acpi_device, wakeup.context);
|
||||
root = acpi_driver_data(adev);
|
||||
pci_pme_wakeup_bus(root->bus);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_acpi_wake_dev - PCI device wakeup notification work function.
|
||||
* @handle: ACPI handle of a device the notification is for.
|
||||
* @work: Work item to handle.
|
||||
* @context: Device wakeup context.
|
||||
*/
|
||||
static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
static void pci_acpi_wake_dev(struct acpi_device_wakeup_context *context)
|
||||
{
|
||||
struct acpi_device_wakeup_context *context;
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
context = container_of(work, struct acpi_device_wakeup_context, work);
|
||||
pci_dev = to_pci_dev(context->dev);
|
||||
|
||||
if (pci_dev->pme_poll)
|
||||
@@ -424,7 +421,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
|
||||
if (pci_dev->current_state == PCI_D3cold) {
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_runtime_resume(&pci_dev->dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -433,7 +430,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
pci_check_pme_status(pci_dev);
|
||||
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_runtime_resume(&pci_dev->dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
|
||||
pci_pme_wakeup_bus(pci_dev->subordinate);
|
||||
}
|
||||
@@ -572,67 +569,29 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
return state_conv[state];
|
||||
}
|
||||
|
||||
static bool acpi_pci_can_wakeup(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
return adev ? acpi_device_can_wakeup(adev) : false;
|
||||
}
|
||||
|
||||
static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
|
||||
static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable)
|
||||
{
|
||||
while (bus->parent) {
|
||||
if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable))
|
||||
return;
|
||||
if (acpi_pm_device_can_wakeup(&bus->self->dev))
|
||||
return acpi_pm_set_device_wakeup(&bus->self->dev, enable);
|
||||
|
||||
bus = bus->parent;
|
||||
}
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
acpi_pm_device_sleep_wake(bus->bridge, enable);
|
||||
}
|
||||
|
||||
static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
if (acpi_pci_can_wakeup(dev))
|
||||
return acpi_pm_device_sleep_wake(&dev->dev, enable);
|
||||
|
||||
acpi_pci_propagate_wakeup_enable(dev->bus, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
|
||||
{
|
||||
while (bus->parent) {
|
||||
struct pci_dev *bridge = bus->self;
|
||||
|
||||
if (bridge->pme_interrupt)
|
||||
return;
|
||||
if (!acpi_pm_device_run_wake(&bridge->dev, enable))
|
||||
return;
|
||||
bus = bus->parent;
|
||||
if (bus->bridge) {
|
||||
if (acpi_pm_device_can_wakeup(bus->bridge))
|
||||
return acpi_pm_set_device_wakeup(bus->bridge, enable);
|
||||
}
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
acpi_pm_device_run_wake(bus->bridge, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
static int acpi_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
/*
|
||||
* Per PCI Express Base Specification Revision 2.0 section
|
||||
* 5.3.3.2 Link Wakeup, platform support is needed for D3cold
|
||||
* waking up to power on the main link even if there is PME
|
||||
* support for D3cold
|
||||
*/
|
||||
if (dev->pme_interrupt && !dev->runtime_d3cold)
|
||||
return 0;
|
||||
if (acpi_pm_device_can_wakeup(&dev->dev))
|
||||
return acpi_pm_set_device_wakeup(&dev->dev, enable);
|
||||
|
||||
if (!acpi_pm_device_run_wake(&dev->dev, enable))
|
||||
return 0;
|
||||
|
||||
acpi_pci_propagate_run_wake(dev->bus, enable);
|
||||
return 0;
|
||||
return acpi_pci_propagate_wakeup(dev->bus, enable);
|
||||
}
|
||||
|
||||
static bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
@@ -656,8 +615,7 @@ static const struct pci_platform_pm_ops acpi_pci_platform_pm = {
|
||||
.set_state = acpi_pci_set_power_state,
|
||||
.get_state = acpi_pci_get_power_state,
|
||||
.choose_state = acpi_pci_choose_state,
|
||||
.sleep_wake = acpi_pci_sleep_wake,
|
||||
.run_wake = acpi_pci_run_wake,
|
||||
.set_wakeup = acpi_pci_wakeup,
|
||||
.need_resume = acpi_pci_need_resume,
|
||||
};
|
||||
|
||||
@@ -780,9 +738,7 @@ static void pci_acpi_setup(struct device *dev)
|
||||
return;
|
||||
|
||||
device_set_wakeup_capable(dev, true);
|
||||
acpi_pci_sleep_wake(pci_dev, false);
|
||||
if (adev->wakeup.flags.run_wake)
|
||||
device_set_run_wake(dev, true);
|
||||
acpi_pci_wakeup(pci_dev, false);
|
||||
}
|
||||
|
||||
static void pci_acpi_cleanup(struct device *dev)
|
||||
@@ -793,10 +749,8 @@ static void pci_acpi_cleanup(struct device *dev)
|
||||
return;
|
||||
|
||||
pci_acpi_remove_pm_notifier(adev);
|
||||
if (adev->wakeup.flags.valid) {
|
||||
if (adev->wakeup.flags.valid)
|
||||
device_set_wakeup_capable(dev, false);
|
||||
device_set_run_wake(dev, false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool pci_acpi_bus_match(struct device *dev)
|
||||
|
@@ -1216,7 +1216,7 @@ static int pci_pm_runtime_resume(struct device *dev)
|
||||
|
||||
pci_restore_standard_config(pci_dev);
|
||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||
__pci_enable_wake(pci_dev, PCI_D0, true, false);
|
||||
pci_enable_wake(pci_dev, PCI_D0, false);
|
||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
||||
|
||||
rc = pm->runtime_resume(dev);
|
||||
|
@@ -39,12 +39,7 @@ static pci_power_t mid_pci_choose_state(struct pci_dev *pdev)
|
||||
return PCI_D3hot;
|
||||
}
|
||||
|
||||
static int mid_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mid_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
static int mid_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -59,8 +54,7 @@ static const struct pci_platform_pm_ops mid_pci_platform_pm = {
|
||||
.set_state = mid_pci_set_power_state,
|
||||
.get_state = mid_pci_get_power_state,
|
||||
.choose_state = mid_pci_choose_state,
|
||||
.sleep_wake = mid_pci_sleep_wake,
|
||||
.run_wake = mid_pci_run_wake,
|
||||
.set_wakeup = mid_pci_wakeup,
|
||||
.need_resume = mid_pci_need_resume,
|
||||
};
|
||||
|
||||
|
@@ -574,8 +574,7 @@ 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->get_state ||
|
||||
!ops->choose_state || !ops->sleep_wake || !ops->run_wake ||
|
||||
!ops->need_resume)
|
||||
!ops->choose_state || !ops->set_wakeup || !ops->need_resume)
|
||||
return -EINVAL;
|
||||
pci_platform_pm = ops;
|
||||
return 0;
|
||||
@@ -603,16 +602,10 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
|
||||
pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
|
||||
}
|
||||
|
||||
static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return pci_platform_pm ?
|
||||
pci_platform_pm->sleep_wake(dev, enable) : -ENODEV;
|
||||
}
|
||||
|
||||
static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return pci_platform_pm ?
|
||||
pci_platform_pm->run_wake(dev, enable) : -ENODEV;
|
||||
pci_platform_pm->set_wakeup(dev, enable) : -ENODEV;
|
||||
}
|
||||
|
||||
static inline bool platform_pci_need_resume(struct pci_dev *dev)
|
||||
@@ -1805,6 +1798,23 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable)
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
}
|
||||
|
||||
static void pci_pme_restore(struct pci_dev *dev)
|
||||
{
|
||||
u16 pmcsr;
|
||||
|
||||
if (!dev->pme_support)
|
||||
return;
|
||||
|
||||
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
|
||||
if (dev->wakeup_prepared) {
|
||||
pmcsr |= PCI_PM_CTRL_PME_ENABLE;
|
||||
} else {
|
||||
pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
|
||||
pmcsr |= PCI_PM_CTRL_PME_STATUS;
|
||||
}
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pme_active - enable or disable PCI device's PME# function
|
||||
* @dev: PCI device to handle.
|
||||
@@ -1872,10 +1882,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
|
||||
EXPORT_SYMBOL(pci_pme_active);
|
||||
|
||||
/**
|
||||
* __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.
|
||||
@@ -1891,17 +1900,18 @@ EXPORT_SYMBOL(pci_pme_active);
|
||||
* 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 runtime, bool enable)
|
||||
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (enable && !runtime && !device_may_wakeup(&dev->dev))
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't do the same thing twice in a row for one device. */
|
||||
if (!!enable == !!dev->wakeup_prepared)
|
||||
/*
|
||||
* Don't do the same thing twice in a row for one device, but restore
|
||||
* PME Enable in case it has been updated by config space restoration.
|
||||
*/
|
||||
if (!!enable == !!dev->wakeup_prepared) {
|
||||
pci_pme_restore(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to "PCI System Architecture" 4th ed. by Tom Shanley & Don
|
||||
@@ -1916,24 +1926,20 @@ int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
|
||||
pci_pme_active(dev, true);
|
||||
else
|
||||
ret = 1;
|
||||
error = runtime ? platform_pci_run_wake(dev, true) :
|
||||
platform_pci_sleep_wake(dev, true);
|
||||
error = platform_pci_set_wakeup(dev, true);
|
||||
if (ret)
|
||||
ret = error;
|
||||
if (!ret)
|
||||
dev->wakeup_prepared = true;
|
||||
} else {
|
||||
if (runtime)
|
||||
platform_pci_run_wake(dev, false);
|
||||
else
|
||||
platform_pci_sleep_wake(dev, false);
|
||||
platform_pci_set_wakeup(dev, false);
|
||||
pci_pme_active(dev, false);
|
||||
dev->wakeup_prepared = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__pci_enable_wake);
|
||||
EXPORT_SYMBOL(pci_enable_wake);
|
||||
|
||||
/**
|
||||
* pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
|
||||
@@ -2075,12 +2081,12 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
|
||||
|
||||
dev->runtime_d3cold = target_state == PCI_D3cold;
|
||||
|
||||
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(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, true, false);
|
||||
pci_enable_wake(dev, target_state, false);
|
||||
dev->runtime_d3cold = false;
|
||||
}
|
||||
|
||||
@@ -2099,7 +2105,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *bus = dev->bus;
|
||||
|
||||
if (device_run_wake(&dev->dev))
|
||||
if (device_can_wakeup(&dev->dev))
|
||||
return true;
|
||||
|
||||
if (!dev->pme_support)
|
||||
@@ -2112,7 +2118,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
while (bus->parent) {
|
||||
struct pci_dev *bridge = bus->self;
|
||||
|
||||
if (device_run_wake(&bridge->dev))
|
||||
if (device_can_wakeup(&bridge->dev))
|
||||
return true;
|
||||
|
||||
bus = bus->parent;
|
||||
@@ -2120,7 +2126,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
return device_run_wake(bus->bridge);
|
||||
return device_can_wakeup(bus->bridge);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -47,11 +47,7 @@ int pci_probe_reset_function(struct pci_dev *dev);
|
||||
* platform; to be used during system-wide transitions from a
|
||||
* sleeping state to the working state and vice versa
|
||||
*
|
||||
* @sleep_wake: enables/disables the system wake up capability of given device
|
||||
*
|
||||
* @run_wake: enables/disables the platform to generate run-time wake-up events
|
||||
* for given device (the device's wake-up capability has to be
|
||||
* enabled by @sleep_wake for this feature to work)
|
||||
* @set_wakeup: enables/disables wakeup capability for the device
|
||||
*
|
||||
* @need_resume: returns 'true' if the given device (which is currently
|
||||
* suspended) needs to be resumed to be configured for system
|
||||
@@ -65,8 +61,7 @@ struct pci_platform_pm_ops {
|
||||
int (*set_state)(struct pci_dev *dev, pci_power_t state);
|
||||
pci_power_t (*get_state)(struct pci_dev *dev);
|
||||
pci_power_t (*choose_state)(struct pci_dev *dev);
|
||||
int (*sleep_wake)(struct pci_dev *dev, bool enable);
|
||||
int (*run_wake)(struct pci_dev *dev, bool enable);
|
||||
int (*set_wakeup)(struct pci_dev *dev, bool enable);
|
||||
bool (*need_resume)(struct pci_dev *dev);
|
||||
};
|
||||
|
||||
|
@@ -294,31 +294,29 @@ static irqreturn_t pcie_pme_irq(int irq, void *context)
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_pme_set_native - Set the PME interrupt flag for given device.
|
||||
* pcie_pme_can_wakeup - Set the wakeup capability flag.
|
||||
* @dev: PCI device to handle.
|
||||
* @ign: Ignored.
|
||||
*/
|
||||
static int pcie_pme_set_native(struct pci_dev *dev, void *ign)
|
||||
static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign)
|
||||
{
|
||||
device_set_run_wake(&dev->dev, true);
|
||||
dev->pme_interrupt = true;
|
||||
device_set_wakeup_capable(&dev->dev, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port.
|
||||
* pcie_pme_mark_devices - Set the wakeup flag for devices below a port.
|
||||
* @port: PCIe root port or event collector to handle.
|
||||
*
|
||||
* For each device below given root port, including the port itself (or for each
|
||||
* root complex integrated endpoint if @port is a root complex event collector)
|
||||
* set the flag indicating that it can signal run-time wake-up events via PCIe
|
||||
* PME interrupts.
|
||||
* set the flag indicating that it can signal run-time wake-up events.
|
||||
*/
|
||||
static void pcie_pme_mark_devices(struct pci_dev *port)
|
||||
{
|
||||
pcie_pme_set_native(port, NULL);
|
||||
pcie_pme_can_wakeup(port, NULL);
|
||||
if (port->subordinate)
|
||||
pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL);
|
||||
pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
مرجع در شماره جدید
Block a user