ACPI / button: Do not propagate wakeup-from-suspend events
During system suspend mark ACPI buttons (other than the lid) as "suspended" and if in that state, report wakeup events on button events, but do not propagate those events up the stack. This prevents systems from being turned off after a button-triggered wakeup from the "freeze" sleep state. Link: https://bugzilla.kernel.org/show_bug.cgi?id=77611 Tested-on: Acer Aspire S5, Toshiba Portege R500 Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
9a3c4145af
commit
e71eeb2a6b
|
@ -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 {
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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;
|
||||||
|
|
Loading…
Reference in a new issue