aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/button.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-07-22 18:59:04 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-07-22 18:59:04 -0400
commite71eeb2a6bcc6282b95215eb353a3ac9ce3e0de3 (patch)
tree6cf8cb0197d889c8bba397e68524e36a8e3a2c5e /drivers/acpi/button.c
parent9a3c4145af32125c5ee39c0272662b47307a8323 (diff)
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>
Diffstat (limited to 'drivers/acpi/button.c')
-rw-r--r--drivers/acpi/button.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index db35594d4df7..6d5d1832a588 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device);
79static void acpi_button_notify(struct acpi_device *device, u32 event); 79static void acpi_button_notify(struct acpi_device *device, u32 event);
80 80
81#ifdef CONFIG_PM_SLEEP 81#ifdef CONFIG_PM_SLEEP
82static int acpi_button_suspend(struct device *dev);
82static int acpi_button_resume(struct device *dev); 83static int acpi_button_resume(struct device *dev);
83#else 84#else
85#define acpi_button_suspend NULL
84#define acpi_button_resume NULL 86#define acpi_button_resume NULL
85#endif 87#endif
86static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); 88static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
87 89
88static struct acpi_driver acpi_button_driver = { 90static struct acpi_driver acpi_button_driver = {
89 .name = "button", 91 .name = "button",
@@ -102,6 +104,7 @@ struct acpi_button {
102 struct input_dev *input; 104 struct input_dev *input;
103 char phys[32]; /* for input device */ 105 char phys[32]; /* for input device */
104 unsigned long pushed; 106 unsigned long pushed;
107 bool suspended;
105}; 108};
106 109
107static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); 110static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
293 if (button->type == ACPI_BUTTON_TYPE_LID) { 296 if (button->type == ACPI_BUTTON_TYPE_LID) {
294 acpi_lid_send_state(device); 297 acpi_lid_send_state(device);
295 } else { 298 } else {
296 int keycode = test_bit(KEY_SLEEP, input->keybit) ? 299 int keycode;
297 KEY_SLEEP : KEY_POWER; 300
301 pm_wakeup_event(&device->dev, 0);
302 if (button->suspended)
303 break;
298 304
305 keycode = test_bit(KEY_SLEEP, input->keybit) ?
306 KEY_SLEEP : KEY_POWER;
299 input_report_key(input, keycode, 1); 307 input_report_key(input, keycode, 1);
300 input_sync(input); 308 input_sync(input);
301 input_report_key(input, keycode, 0); 309 input_report_key(input, keycode, 0);
302 input_sync(input); 310 input_sync(input);
303 311
304 pm_wakeup_event(&device->dev, 0);
305 acpi_bus_generate_netlink_event( 312 acpi_bus_generate_netlink_event(
306 device->pnp.device_class, 313 device->pnp.device_class,
307 dev_name(&device->dev), 314 dev_name(&device->dev),
@@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
316} 323}
317 324
318#ifdef CONFIG_PM_SLEEP 325#ifdef CONFIG_PM_SLEEP
326static int acpi_button_suspend(struct device *dev)
327{
328 struct acpi_device *device = to_acpi_device(dev);
329 struct acpi_button *button = acpi_driver_data(device);
330
331 button->suspended = true;
332 return 0;
333}
334
319static int acpi_button_resume(struct device *dev) 335static int acpi_button_resume(struct device *dev)
320{ 336{
321 struct acpi_device *device = to_acpi_device(dev); 337 struct acpi_device *device = to_acpi_device(dev);
322 struct acpi_button *button = acpi_driver_data(device); 338 struct acpi_button *button = acpi_driver_data(device);
323 339
340 button->suspended = false;
324 if (button->type == ACPI_BUTTON_TYPE_LID) 341 if (button->type == ACPI_BUTTON_TYPE_LID)
325 return acpi_lid_send_state(device); 342 return acpi_lid_send_state(device);
326 return 0; 343 return 0;