Commit 805c5281 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-pm', 'acpi-sleep' and 'acpi-button'

* acpi-pm:
  ACPI / PM: Use ACPI_COMPANION() instead of ACPI_HANDLE()
  ACPI / PM: Always enable wakeup GPEs when enabling device wakeup
  ACPI / PM: Revork the handling of ACPI device wakeup notifications
  PM: Create PM workqueue if runtime PM is not configured too

* acpi-sleep:
  ACPI / sleep: Do not save NVS for new machines to accelerate S3

* acpi-button:
  ACPI / button: Do not propagate wakeup-from-suspend events
...@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device); ...@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device);
static void acpi_button_notify(struct acpi_device *device, u32 event); static void acpi_button_notify(struct acpi_device *device, u32 event);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int acpi_button_suspend(struct device *dev);
static int acpi_button_resume(struct device *dev); static int acpi_button_resume(struct device *dev);
#else #else
#define acpi_button_suspend NULL
#define acpi_button_resume NULL #define acpi_button_resume NULL
#endif #endif
static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
static struct acpi_driver acpi_button_driver = { static struct acpi_driver acpi_button_driver = {
.name = "button", .name = "button",
...@@ -102,6 +104,7 @@ struct acpi_button { ...@@ -102,6 +104,7 @@ struct acpi_button {
struct input_dev *input; struct input_dev *input;
char phys[32]; /* for input device */ char phys[32]; /* for input device */
unsigned long pushed; unsigned long pushed;
bool suspended;
}; };
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
...@@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) ...@@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
if (button->type == ACPI_BUTTON_TYPE_LID) { if (button->type == ACPI_BUTTON_TYPE_LID) {
acpi_lid_send_state(device); acpi_lid_send_state(device);
} else { } else {
int keycode = test_bit(KEY_SLEEP, input->keybit) ? int keycode;
KEY_SLEEP : KEY_POWER;
pm_wakeup_event(&device->dev, 0);
if (button->suspended)
break;
keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
input_report_key(input, keycode, 1); input_report_key(input, keycode, 1);
input_sync(input); input_sync(input);
input_report_key(input, keycode, 0); input_report_key(input, keycode, 0);
input_sync(input); input_sync(input);
pm_wakeup_event(&device->dev, 0);
acpi_bus_generate_netlink_event( acpi_bus_generate_netlink_event(
device->pnp.device_class, device->pnp.device_class,
dev_name(&device->dev), dev_name(&device->dev),
...@@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) ...@@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int acpi_button_suspend(struct device *dev)
{
struct acpi_device *device = to_acpi_device(dev);
struct acpi_button *button = acpi_driver_data(device);
button->suspended = true;
return 0;
}
static int acpi_button_resume(struct device *dev) static int acpi_button_resume(struct device *dev)
{ {
struct acpi_device *device = to_acpi_device(dev); struct acpi_device *device = to_acpi_device(dev);
struct acpi_button *button = acpi_driver_data(device); struct acpi_button *button = acpi_driver_data(device);
button->suspended = false;
if (button->type == ACPI_BUTTON_TYPE_LID) if (button->type == ACPI_BUTTON_TYPE_LID)
return acpi_lid_send_state(device); return acpi_lid_send_state(device);
return 0; return 0;
......
...@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable); ...@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static DEFINE_MUTEX(acpi_pm_notifier_lock); static DEFINE_MUTEX(acpi_pm_notifier_lock);
static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
{
struct acpi_device *adev;
if (val != ACPI_NOTIFY_DEVICE_WAKE)
return;
adev = acpi_bus_get_acpi_device(handle);
if (!adev)
return;
mutex_lock(&acpi_pm_notifier_lock);
if (adev->wakeup.flags.notifier_present) {
__pm_wakeup_event(adev->wakeup.ws, 0);
if (adev->wakeup.context.work.func)
queue_pm_work(&adev->wakeup.context.work);
}
mutex_unlock(&acpi_pm_notifier_lock);
acpi_bus_put_acpi_device(adev);
}
/** /**
* acpi_add_pm_notifier - Register PM notifier for given ACPI device. * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
* @adev: ACPI device to add the notifier for. * @adev: ACPI device to add the notify handler for.
* @context: Context information to pass to the notifier routine. * @dev: Device to generate a wakeup event for while handling the notification.
* @work_func: Work function to execute when handling the notification.
* *
* NOTE: @adev need not be a run-wake or wakeup device to be a valid source of * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
* PM wakeup events. For example, wakeup events may be generated for bridges * PM wakeup events. For example, wakeup events may be generated for bridges
* if one of the devices below the bridge is signaling wakeup, even if the * if one of the devices below the bridge is signaling wakeup, even if the
* bridge itself doesn't have a wakeup GPE associated with it. * bridge itself doesn't have a wakeup GPE associated with it.
*/ */
acpi_status acpi_add_pm_notifier(struct acpi_device *adev, acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
acpi_notify_handler handler, void *context) void (*work_func)(struct work_struct *work))
{ {
acpi_status status = AE_ALREADY_EXISTS; acpi_status status = AE_ALREADY_EXISTS;
if (!dev && !work_func)
return AE_BAD_PARAMETER;
mutex_lock(&acpi_pm_notifier_lock); mutex_lock(&acpi_pm_notifier_lock);
if (adev->wakeup.flags.notifier_present) if (adev->wakeup.flags.notifier_present)
goto out; goto out;
status = acpi_install_notify_handler(adev->handle, adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
ACPI_SYSTEM_NOTIFY, adev->wakeup.context.dev = dev;
handler, context); if (work_func)
INIT_WORK(&adev->wakeup.context.work, work_func);
status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
acpi_pm_notify_handler, NULL);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
goto out; goto out;
...@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, ...@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
* acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
* @adev: ACPI device to remove the notifier from. * @adev: ACPI device to remove the notifier from.
*/ */
acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
acpi_notify_handler handler)
{ {
acpi_status status = AE_BAD_PARAMETER; acpi_status status = AE_BAD_PARAMETER;
...@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, ...@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
status = acpi_remove_notify_handler(adev->handle, status = acpi_remove_notify_handler(adev->handle,
ACPI_SYSTEM_NOTIFY, ACPI_SYSTEM_NOTIFY,
handler); acpi_pm_notify_handler);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
goto out; goto out;
if (adev->wakeup.context.work.func) {
cancel_work_sync(&adev->wakeup.context.work);
adev->wakeup.context.work.func = NULL;
}
adev->wakeup.context.dev = NULL;
wakeup_source_unregister(adev->wakeup.ws);
adev->wakeup.flags.notifier_present = false; adev->wakeup.flags.notifier_present = false;
out: out:
...@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, ...@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
*/ */
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
{ {
acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev; struct acpi_device *adev;
int ret, d_min, d_max; int ret, d_min, d_max;
...@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) ...@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
d_max_in = ACPI_STATE_D3_HOT; d_max_in = ACPI_STATE_D3_HOT;
} }
if (!handle || acpi_bus_get_device(handle, &adev)) { adev = ACPI_COMPANION(dev);
dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); if (!adev) {
dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
return -ENODEV; return -ENODEV;
} }
...@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) ...@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
} }
EXPORT_SYMBOL(acpi_pm_device_sleep_state); EXPORT_SYMBOL(acpi_pm_device_sleep_state);
#ifdef CONFIG_PM_RUNTIME
/** /**
* acpi_wakeup_device - Wakeup notification handler for ACPI devices. * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
* @handle: ACPI handle of the device the notification is for. * @work: Work item to handle.
* @event: Type of the signaled event.
* @context: Device corresponding to @handle.
*/ */
static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) static void acpi_pm_notify_work_func(struct work_struct *work)
{ {
struct device *dev = context; struct device *dev;
if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
if (dev) {
pm_wakeup_event(dev, 0); pm_wakeup_event(dev, 0);
pm_runtime_resume(dev); pm_runtime_resume(dev);
} }
} }
/** /**
* __acpi_device_run_wake - Enable/disable runtime remote wakeup for device. * acpi_device_wakeup - Enable/disable wakeup functionality for device.
* @adev: ACPI device to enable/disable the remote wakeup for. * @adev: ACPI device to enable/disable wakeup functionality for.
* @target_state: State the system is transitioning into.
* @enable: Whether to enable or disable the wakeup functionality. * @enable: Whether to enable or disable the wakeup functionality.
* *
* Enable/disable the GPE associated with @adev so that it can generate * Enable/disable the GPE associated with @adev so that it can generate
...@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) ...@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
* Callers must ensure that @adev is a valid ACPI device node before executing * Callers must ensure that @adev is a valid ACPI device node before executing
* this function. * this function.
*/ */
int __acpi_device_run_wake(struct acpi_device *adev, bool enable) static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state,
bool enable)
{ {
struct acpi_device_wakeup *wakeup = &adev->wakeup; struct acpi_device_wakeup *wakeup = &adev->wakeup;
...@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) ...@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
acpi_status res; acpi_status res;
int error; int error;
error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0); error = acpi_enable_wakeup_device_power(adev, target_state);
if (error) if (error)
return error; return error;
...@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) ...@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
return 0; return 0;
} }
#ifdef CONFIG_PM_RUNTIME
/** /**
* acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
* @dev: Device to enable/disable the platform to wake up. * @dev: Device to enable/disable the platform to wake up.
...@@ -661,41 +700,22 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) ...@@ -661,41 +700,22 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
{ {
struct acpi_device *adev; struct acpi_device *adev;
acpi_handle handle;
if (!device_run_wake(phys_dev)) if (!device_run_wake(phys_dev))
return -EINVAL; return -EINVAL;
handle = ACPI_HANDLE(phys_dev); adev = ACPI_COMPANION(phys_dev);
if (!handle || acpi_bus_get_device(handle, &adev)) { if (!adev) {
dev_dbg(phys_dev, "ACPI handle without context in %s!\n", dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__);
__func__);
return -ENODEV; return -ENODEV;
} }
return __acpi_device_run_wake(adev, enable); return acpi_device_wakeup(adev, enable, ACPI_STATE_S0);
} }
EXPORT_SYMBOL(acpi_pm_device_run_wake); EXPORT_SYMBOL(acpi_pm_device_run_wake);
#else
static inline void acpi_wakeup_device(acpi_handle handle, u32 event,
void *context) {}
#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/**
* __acpi_device_sleep_wake - Enable or disable device to wake up the system.
* @dev: Device to enable/desible to wake up the system.
* @target_state: System state the device is supposed to wake up from.
* @enable: Whether to enable or disable @dev to wake up the system.
*/
int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
bool enable)
{
return enable ?
acpi_enable_wakeup_device_power(adev, target_state) :
acpi_disable_wakeup_device_power(adev);
}
/** /**
* acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
* @dev: Device to enable/desible to wake up the system from sleep states. * @dev: Device to enable/desible to wake up the system from sleep states.
...@@ -703,21 +723,19 @@ int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state, ...@@ -703,21 +723,19 @@ int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
*/ */
int acpi_pm_device_sleep_wake(struct device *dev, bool enable) int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
{ {
acpi_handle handle;
struct acpi_device *adev; struct acpi_device *adev;
int error; int error;
if (!device_can_wakeup(dev)) if (!device_can_wakeup(dev))
return -EINVAL; return -EINVAL;
handle = ACPI_HANDLE(dev); adev = ACPI_COMPANION(dev);
if (!handle || acpi_bus_get_device(handle, &adev)) { if (!adev) {
dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
return -ENODEV; return -ENODEV;
} }
error = __acpi_device_sleep_wake(adev, acpi_target_system_state(), error = acpi_device_wakeup(adev, acpi_target_system_state(), enable);
enable);
if (!error) if (!error)
dev_info(dev, "System wakeup %s by ACPI\n", dev_info(dev, "System wakeup %s by ACPI\n",
enable ? "enabled" : "disabled"); enable ? "enabled" : "disabled");
...@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev) ...@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev)
remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
PM_QOS_FLAGS_NONE; PM_QOS_FLAGS_NONE;
error = __acpi_device_run_wake(adev, remote_wakeup); error = acpi_device_wakeup(adev, ACPI_STATE_S0, remote_wakeup);
if (remote_wakeup && error) if (remote_wakeup && error)
return -EAGAIN; return -EAGAIN;
error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
if (error) if (error)
__acpi_device_run_wake(adev, false); acpi_device_wakeup(adev, ACPI_STATE_S0, false);
return error; return error;
} }
...@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev) ...@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev)
return 0; return 0;
error = acpi_dev_pm_full_power(adev); error = acpi_dev_pm_full_power(adev);
__acpi_device_run_wake(adev, false); acpi_device_wakeup(adev, ACPI_STATE_S0, false);
return error; return error;
} }
EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
...@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev) ...@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev)
target_state = acpi_target_system_state(); target_state = acpi_target_system_state();
wakeup = device_may_wakeup(dev); wakeup = device_may_wakeup(dev);
error = __acpi_device_sleep_wake(adev, target_state, wakeup); error = acpi_device_wakeup(adev, target_state, wakeup);
if (wakeup && error) if (wakeup && error)
return error; return error;
error = acpi_dev_pm_low_power(dev, adev, target_state); error = acpi_dev_pm_low_power(dev, adev, target_state);
if (error) if (error)
__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
return error; return error;
} }
...@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev) ...@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev)
return 0; return 0;
error = acpi_dev_pm_full_power(adev); error = acpi_dev_pm_full_power(adev);
__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
return error; return error;
} }
EXPORT_SYMBOL_GPL(acpi_dev_resume_early); EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
...@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) ...@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
if (dev->pm_domain) if (dev->pm_domain)
return -EEXIST; return -EEXIST;
acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
dev->pm_domain = &acpi_general_pm_domain; dev->pm_domain = &acpi_general_pm_domain;
if (power_on) { if (power_on) {
acpi_dev_pm_full_power(adev); acpi_dev_pm_full_power(adev);
__acpi_device_run_wake(adev, false); acpi_device_wakeup(adev, ACPI_STATE_S0, false);
} }
return 0; return 0;
} }
...@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) ...@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
if (adev && dev->pm_domain == &acpi_general_pm_domain) { if (adev && dev->pm_domain == &acpi_general_pm_domain) {
dev->pm_domain = NULL; dev->pm_domain = NULL;
acpi_remove_pm_notifier(adev, acpi_wakeup_device); acpi_remove_pm_notifier(adev);
if (power_off) { if (power_off) {
/* /*
* If the device's PM QoS resume latency limit or flags * If the device's PM QoS resume latency limit or flags
...@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) ...@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
*/ */
dev_pm_qos_hide_latency_limit(dev); dev_pm_qos_hide_latency_limit(dev);
dev_pm_qos_hide_flags(dev); dev_pm_qos_hide_flags(dev);
__acpi_device_run_wake(adev, false); acpi_device_wakeup(adev, ACPI_STATE_S0, false);
acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
} }
} }
......
...@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device, ...@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (no_aspm) if (no_aspm)
pcie_no_aspm(); pcie_no_aspm();
pci_acpi_add_bus_pm_notifier(device, root->bus); pci_acpi_add_bus_pm_notifier(device);
if (device->wakeup.flags.run_wake) if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true); device_set_run_wake(root->bus->bridge, true);
......
...@@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = { ...@@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = {
static void acpi_sleep_dmi_check(void) static void acpi_sleep_dmi_check(void)
{ {
int year;
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
acpi_nvs_nosave_s3();
dmi_check_system(acpisleep_dmi_table); dmi_check_system(acpisleep_dmi_table);
} }
......
...@@ -18,31 +18,31 @@ ...@@ -18,31 +18,31 @@
#include "pci.h" #include "pci.h"
/** /**
* pci_acpi_wake_bus - Wake-up notification handler for root buses. * pci_acpi_wake_bus - Root bus wakeup notification fork function.
* @handle: ACPI handle of a device the notification is for. * @work: Work item to handle.
* @event: Type of the signaled event.
* @context: PCI root bus to wake up devices on.
*/ */
static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) static void pci_acpi_wake_bus(struct work_struct *work)
{ {
struct pci_bus *pci_bus = context; struct acpi_device *adev;
struct acpi_pci_root *root;
if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) adev = container_of(work, struct acpi_device, wakeup.context.work);
pci_pme_wakeup_bus(pci_bus); root = acpi_driver_data(adev);
pci_pme_wakeup_bus(root->bus);
} }
/** /**
* pci_acpi_wake_dev - Wake-up notification handler for PCI devices. * pci_acpi_wake_dev - PCI device wakeup notification work function.
* @handle: ACPI handle of a device the notification is for. * @handle: ACPI handle of a device the notification is for.
* @event: Type of the signaled event. * @work: Work item to handle.
* @context: PCI device object to wake up.
*/ */
static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) static void pci_acpi_wake_dev(struct work_struct *work)
{ {
struct pci_dev *pci_dev = context; struct acpi_device_wakeup_context *context;
struct pci_dev *pci_dev;
if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) context = container_of(work, struct acpi_device_wakeup_context, work);
return; pci_dev = to_pci_dev(context->dev);
if (pci_dev->pme_poll) if (pci_dev->pme_poll)
pci_dev->pme_poll = false; pci_dev->pme_poll = false;
...@@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) ...@@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
} }
/** /**
* pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. * pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus.
* @dev: ACPI device to add the notifier for. * @dev: PCI root bridge ACPI device.
* @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
*/ */
acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev)
struct pci_bus *pci_bus)
{ {
return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus);
}
/**
* pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier.
* @dev: ACPI device to remove the notifier from.
*/
acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
{
return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
} }
/** /**
...@@ -92,16 +81,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) ...@@ -92,16 +81,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
struct pci_dev *pci_dev) struct pci_dev *pci_dev)
{ {
return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); return acpi_add_pm_notifier(dev, &pci_dev->dev, pci_acpi_wake_dev);
}
/**
* pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier.
* @dev: ACPI device to remove the notifier from.
*/
acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
{
return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
} }
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
......
...@@ -315,12 +315,19 @@ struct acpi_device_wakeup_flags { ...@@ -315,12 +315,19 @@ struct acpi_device_wakeup_flags {
u8 notifier_present:1; /* Wake-up notify handler has been installed */ u8 notifier_present:1; /* Wake-up notify handler has been installed */
}; };
struct acpi_device_wakeup_context {
struct work_struct work;
struct device *dev;
};
struct acpi_device_wakeup { struct acpi_device_wakeup {
acpi_handle gpe_device; acpi_handle gpe_device;
u64 gpe_number; u64 gpe_number;
u64 sleep_state; u64 sleep_state;
struct list_head resources; struct list_head resources;
struct acpi_device_wakeup_flags flags; struct acpi_device_wakeup_flags flags;
struct acpi_device_wakeup_context context;
struct wakeup_source *ws;
int prepare_count; int prepare_count;
}; };
...@@ -510,20 +517,18 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); ...@@ -510,20 +517,18 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
int acpi_disable_wakeup_device_power(struct acpi_device *dev); int acpi_disable_wakeup_device_power(struct acpi_device *dev);
#ifdef CONFIG_PM #ifdef CONFIG_PM
acpi_status acpi_add_pm_notifier(struct acpi_device *adev, acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
acpi_notify_handler handler, void *context); void (*work_func)(struct work_struct *work));
acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, acpi_status acpi_remove_pm_notifier(struct acpi_device *adev);
acpi_notify_handler handler);
int acpi_pm_device_sleep_state(struct device *, int *, int); int acpi_pm_device_sleep_state(struct device *, int *, int);
#else #else
static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
acpi_notify_handler handler, struct device *dev,
void *context) void (*work_func)(struct work_struct *work))
{ {
return AE_SUPPORT; return AE_SUPPORT;
} }
static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
acpi_notify_handler handler)
{ {
return AE_SUPPORT; return AE_SUPPORT;
} }
...@@ -538,13 +543,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) ...@@ -538,13 +543,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
#endif #endif
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
int __acpi_device_run_wake(struct acpi_device *, bool);
int acpi_pm_device_run_wake(struct device *, bool); int acpi_pm_device_run_wake(struct device *, bool);
#else #else
static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en)
{
return -ENODEV;
}
static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
{ {
return -ENODEV; return -ENODEV;
...@@ -552,14 +552,8 @@ static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) ...@@ -552,14 +552,8 @@ static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
#endif #endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
int __acpi_device_sleep_wake(struct acpi_device *, u32, bool);
int acpi_pm_device_sleep_wake(struct device *, bool); int acpi_pm_device_sleep_wake(struct device *, bool);
#else #else
static inline int __acpi_device_sleep_wake(struct acpi_device *adev,
u32 target_state, bool enable)
{
return -ENODEV;
}
static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
{ {
return -ENODEV; return -ENODEV;
......
...@@ -11,12 +11,17 @@ ...@@ -11,12 +11,17 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev);
struct pci_bus *pci_bus); static inline acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); {
return acpi_remove_pm_notifier(dev);
}
extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
struct pci_dev *pci_dev); struct pci_dev *pci_dev);
extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
{
return acpi_remove_pm_notifier(dev);
}
extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle); extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
......
...@@ -24,11 +24,20 @@ ...@@ -24,11 +24,20 @@
#define RPM_AUTO 0x08 /* Use autosuspend_delay */ #define RPM_AUTO 0x08 /* Use autosuspend_delay */
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern struct workqueue_struct *pm_wq;
static inline bool queue_pm_work(struct work_struct *work)
{
return queue_work(pm_wq, work);
}
extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_suspend(struct device *dev);
extern int pm_generic_runtime_resume(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev);
extern int pm_runtime_force_suspend(struct device *dev); extern int pm_runtime_force_suspend(struct device *dev);
extern int pm_runtime_force_resume(struct device *dev); extern int pm_runtime_force_resume(struct device *dev);
#else #else
static inline bool queue_pm_work(struct work_struct *work) { return false; }
static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
static inline int pm_runtime_force_suspend(struct device *dev) { return 0; } static inline int pm_runtime_force_suspend(struct device *dev) { return 0; }
...@@ -37,8 +46,6 @@ static inline int pm_runtime_force_resume(struct device *dev) { return 0; } ...@@ -37,8 +46,6 @@ static inline int pm_runtime_force_resume(struct device *dev) { return 0; }
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
extern struct workqueue_struct *pm_wq;
extern int __pm_runtime_idle(struct device *dev, int rpmflags); extern int __pm_runtime_idle(struct device *dev, int rpmflags);
extern int __pm_runtime_suspend(struct device *dev, int rpmflags); extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
extern int __pm_runtime_resume(struct device *dev, int rpmflags); extern int __pm_runtime_resume(struct device *dev, int rpmflags);
......
...@@ -615,7 +615,6 @@ static struct attribute_group attr_group = { ...@@ -615,7 +615,6 @@ static struct attribute_group attr_group = {
.attrs = g, .attrs = g,
}; };
#ifdef CONFIG_PM_RUNTIME
struct workqueue_struct *pm_wq; struct workqueue_struct *pm_wq;
EXPORT_SYMBOL_GPL(pm_wq); EXPORT_SYMBOL_GPL(pm_wq);
...@@ -625,9 +624,6 @@ static int __init pm_start_workqueue(void) ...@@ -625,9 +624,6 @@ static int __init pm_start_workqueue(void)
return pm_wq ? 0 : -ENOMEM; return pm_wq ? 0 : -ENOMEM;
} }
#else
static inline int pm_start_workqueue(void) { return 0; }
#endif
static int __init pm_init(void) static int __init pm_init(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment