Skip to content

Commit

Permalink
ACPI / button: Do not propagate wakeup-from-suspend events
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rafael J. Wysocki committed Jul 22, 2014
1 parent 9a3c414 commit e71eeb2
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions drivers/acpi/button.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device);
static void acpi_button_notify(struct acpi_device *device, u32 event);

#ifdef CONFIG_PM_SLEEP
static int acpi_button_suspend(struct device *dev);
static int acpi_button_resume(struct device *dev);
#else
#define acpi_button_suspend NULL
#define acpi_button_resume NULL
#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 = {
.name = "button",
Expand All @@ -102,6 +104,7 @@ struct acpi_button {
struct input_dev *input;
char phys[32]; /* for input device */
unsigned long pushed;
bool suspended;
};

static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
Expand Down Expand Up @@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
if (button->type == ACPI_BUTTON_TYPE_LID) {
acpi_lid_send_state(device);
} else {
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
int keycode;

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_sync(input);
input_report_key(input, keycode, 0);
input_sync(input);

pm_wakeup_event(&device->dev, 0);
acpi_bus_generate_netlink_event(
device->pnp.device_class,
dev_name(&device->dev),
Expand All @@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
}

#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)
{
struct acpi_device *device = to_acpi_device(dev);
struct acpi_button *button = acpi_driver_data(device);

button->suspended = false;
if (button->type == ACPI_BUTTON_TYPE_LID)
return acpi_lid_send_state(device);
return 0;
Expand Down

0 comments on commit e71eeb2

Please sign in to comment.