aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/button.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2017-09-11 10:07:06 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-08 18:30:44 -0500
commit84d3f6b76447896919c63b28ad71f71238cefcce (patch)
tree0ee00fa0c6532ba48342e55011e38b972774a79c /drivers/acpi/button.c
parent39dae59d66acd86d1de24294bd2f343fd5e7a625 (diff)
ACPI / button: Delay acpi_lid_initialize_state() until first user space open
ACPI _LID methods may depend on OpRegions and do not always handle handlers for those OpRegions not being present properly e.g. : Method (_LID, 0, NotSerialized) // _LID: Lid Status { If ((^^I2C5.PMI1.AVBL == One) && (^^GPO2.AVBL == One)) { Return (^^GPO2.LPOL) /* \_SB_.GPO2.LPOL */ } } Note the missing Return (1) when either of the OpRegions is not available, this causes (in this case) a report of the lid-switch being closed, which causes userspace to do an immediate suspend at boot. This commit delays getting the initial state and thus calling _LID for the first time until userspace opens the /dev/input/event# node. This ensures that all drivers will have had a chance to load and registerer their OpRegions before the first _LID call, fixing this issue. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/button.c')
-rw-r--r--drivers/acpi/button.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index ef1856b15488..c391898b483c 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -390,6 +390,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
390{ 390{
391 struct acpi_button *button = acpi_driver_data(device); 391 struct acpi_button *button = acpi_driver_data(device);
392 struct input_dev *input; 392 struct input_dev *input;
393 int users;
393 394
394 switch (event) { 395 switch (event) {
395 case ACPI_FIXED_HARDWARE_EVENT: 396 case ACPI_FIXED_HARDWARE_EVENT:
@@ -398,7 +399,11 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
398 case ACPI_BUTTON_NOTIFY_STATUS: 399 case ACPI_BUTTON_NOTIFY_STATUS:
399 input = button->input; 400 input = button->input;
400 if (button->type == ACPI_BUTTON_TYPE_LID) { 401 if (button->type == ACPI_BUTTON_TYPE_LID) {
401 acpi_lid_update_state(device); 402 mutex_lock(&button->input->mutex);
403 users = button->input->users;
404 mutex_unlock(&button->input->mutex);
405 if (users)
406 acpi_lid_update_state(device);
402 } else { 407 } else {
403 int keycode; 408 int keycode;
404 409
@@ -442,12 +447,24 @@ static int acpi_button_resume(struct device *dev)
442 struct acpi_button *button = acpi_driver_data(device); 447 struct acpi_button *button = acpi_driver_data(device);
443 448
444 button->suspended = false; 449 button->suspended = false;
445 if (button->type == ACPI_BUTTON_TYPE_LID) 450 if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users)
446 acpi_lid_initialize_state(device); 451 acpi_lid_initialize_state(device);
447 return 0; 452 return 0;
448} 453}
449#endif 454#endif
450 455
456static int acpi_lid_input_open(struct input_dev *input)
457{
458 struct acpi_device *device = input_get_drvdata(input);
459 struct acpi_button *button = acpi_driver_data(device);
460
461 button->last_state = !!acpi_lid_evaluate_state(device);
462 button->last_time = ktime_get();
463 acpi_lid_initialize_state(device);
464
465 return 0;
466}
467
451static int acpi_button_add(struct acpi_device *device) 468static int acpi_button_add(struct acpi_device *device)
452{ 469{
453 struct acpi_button *button; 470 struct acpi_button *button;
@@ -488,8 +505,7 @@ static int acpi_button_add(struct acpi_device *device)
488 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); 505 strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
489 sprintf(class, "%s/%s", 506 sprintf(class, "%s/%s",
490 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); 507 ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
491 button->last_state = !!acpi_lid_evaluate_state(device); 508 input->open = acpi_lid_input_open;
492 button->last_time = ktime_get();
493 } else { 509 } else {
494 printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); 510 printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
495 error = -ENODEV; 511 error = -ENODEV;
@@ -522,11 +538,11 @@ static int acpi_button_add(struct acpi_device *device)
522 break; 538 break;
523 } 539 }
524 540
541 input_set_drvdata(input, device);
525 error = input_register_device(input); 542 error = input_register_device(input);
526 if (error) 543 if (error)
527 goto err_remove_fs; 544 goto err_remove_fs;
528 if (button->type == ACPI_BUTTON_TYPE_LID) { 545 if (button->type == ACPI_BUTTON_TYPE_LID) {
529 acpi_lid_initialize_state(device);
530 /* 546 /*
531 * This assumes there's only one lid device, or if there are 547 * This assumes there's only one lid device, or if there are
532 * more we only care about the last one... 548 * more we only care about the last one...