| From 21988a8e51479ceffe7b0568b170effabb708dfe Mon Sep 17 00:00:00 2001 |
| From: "dmitry.torokhov@gmail.com" <dmitry.torokhov@gmail.com> |
| Date: Sun, 4 Oct 2020 22:11:25 -0700 |
| Subject: ACPI: button: fix handling lid state changes when input device closed |
| |
| From: dmitry.torokhov@gmail.com <dmitry.torokhov@gmail.com> |
| |
| commit 21988a8e51479ceffe7b0568b170effabb708dfe upstream. |
| |
| The original intent of 84d3f6b76447 was to delay evaluating lid state until |
| all drivers have been loaded, with input device being opened from userspace |
| serving as a signal for this condition. Let's ensure that state updates |
| happen even if userspace closed (or in the future inhibited) input device. |
| |
| Note that if we go through suspend/resume cycle we assume the system has |
| been fully initialized even if LID input device has not been opened yet. |
| |
| This has a side-effect of fixing access to input->users outside of |
| input->mutex protections by the way of eliminating said accesses and using |
| driver private flag. |
| |
| Fixes: 84d3f6b76447 ("ACPI / button: Delay acpi_lid_initialize_state() until first user space open") |
| Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| Reviewed-by: Hans de Goede <hdegoede@redhat.com> |
| Cc: 4.15+ <stable@vger.kernel.org> # 4.15+ |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/acpi/button.c | 13 +++++++------ |
| 1 file changed, 7 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/acpi/button.c |
| +++ b/drivers/acpi/button.c |
| @@ -153,6 +153,7 @@ struct acpi_button { |
| int last_state; |
| ktime_t last_time; |
| bool suspended; |
| + bool lid_state_initialized; |
| }; |
| |
| static struct acpi_device *lid_device; |
| @@ -383,6 +384,8 @@ static int acpi_lid_update_state(struct |
| |
| static void acpi_lid_initialize_state(struct acpi_device *device) |
| { |
| + struct acpi_button *button = acpi_driver_data(device); |
| + |
| switch (lid_init_state) { |
| case ACPI_BUTTON_LID_INIT_OPEN: |
| (void)acpi_lid_notify_state(device, 1); |
| @@ -394,13 +397,14 @@ static void acpi_lid_initialize_state(st |
| default: |
| break; |
| } |
| + |
| + button->lid_state_initialized = true; |
| } |
| |
| static void acpi_button_notify(struct acpi_device *device, u32 event) |
| { |
| struct acpi_button *button = acpi_driver_data(device); |
| struct input_dev *input; |
| - int users; |
| |
| switch (event) { |
| case ACPI_FIXED_HARDWARE_EVENT: |
| @@ -409,10 +413,7 @@ static void acpi_button_notify(struct ac |
| case ACPI_BUTTON_NOTIFY_STATUS: |
| input = button->input; |
| if (button->type == ACPI_BUTTON_TYPE_LID) { |
| - mutex_lock(&button->input->mutex); |
| - users = button->input->users; |
| - mutex_unlock(&button->input->mutex); |
| - if (users) |
| + if (button->lid_state_initialized) |
| acpi_lid_update_state(device, true); |
| } else { |
| int keycode; |
| @@ -457,7 +458,7 @@ static int acpi_button_resume(struct dev |
| struct acpi_button *button = acpi_driver_data(device); |
| |
| button->suspended = false; |
| - if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) { |
| + if (button->type == ACPI_BUTTON_TYPE_LID) { |
| button->last_state = !!acpi_lid_evaluate_state(device); |
| button->last_time = ktime_get(); |
| acpi_lid_initialize_state(device); |