Currently logic for installing notifications from ACPI devices is implemented using notify callback in struct acpi_driver. Preparations are being made to replace acpi_driver with more generic struct platform_driver, which doesn't contain notify callback. Furthermore as of now handlers are being called indirectly through acpi_notify_device(), which decreases performance. Call acpi_device_install_event_handler() at the end of .add() callback. Call acpi_device_remove_event_handler() at the beginning of .remove() callback. Change arguments passed to the notify callback to match with what's required by acpi_device_install_event_handler(). Signed-off-by: Michal Wilczynski <michal.wilczynski@xxxxxxxxx> --- drivers/platform/x86/fujitsu-laptop.c | 103 ++++++++++++++------------ 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 085e044e888e..41b5bdca859a 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -769,6 +769,54 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) return 0; } +static void acpi_fujitsu_laptop_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *device = data; + struct fujitsu_laptop *priv; + unsigned long flags; + int scancode, i = 0; + unsigned int irb; + + priv = acpi_driver_data(device); + + if (event != ACPI_FUJITSU_NOTIFY_CODE) { + acpi_handle_info(device->handle, "Unsupported event [0x%x]\n", + event); + sparse_keymap_report_event(priv->input, -1, 1, true); + return; + } + + if (priv->flags_supported) + priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, + 0x0); + + while ((irb = call_fext_func(device, + FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 && + i++ < MAX_HOTKEY_RINGBUFFER_SIZE) { + scancode = irb & 0x4ff; + if (sparse_keymap_entry_from_scancode(priv->input, scancode)) + acpi_fujitsu_laptop_press(device, scancode); + else if (scancode == 0) + acpi_fujitsu_laptop_release(device); + else + acpi_handle_info(device->handle, + "Unknown GIRB result [%x]\n", irb); + } + + /* + * First seen on the Skylake-based Lifebook E736/E746/E756), the + * touchpad toggle hotkey (Fn+F4) is handled in software. Other models + * have since added additional "soft keys". These are reported in the + * status flags queried using FUNC_FLAGS. + */ + if (priv->flags_supported & (FLAG_SOFTKEYS)) { + flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0); + flags &= (FLAG_SOFTKEYS); + for_each_set_bit(i, &flags, BITS_PER_LONG) + sparse_keymap_report_event(priv->input, BIT(i), 1, true); + } +} + static int acpi_fujitsu_laptop_add(struct acpi_device *device) { struct fujitsu_laptop *priv; @@ -839,7 +887,12 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device) if (ret) goto err_free_fifo; - return 0; + ret = acpi_device_install_event_handler(device, ACPI_DEVICE_NOTIFY, + acpi_fujitsu_laptop_notify); + if (ret) + goto err_free_fifo; + + return ret; err_free_fifo: kfifo_free(&priv->fifo); @@ -851,6 +904,8 @@ static void acpi_fujitsu_laptop_remove(struct acpi_device *device) { struct fujitsu_laptop *priv = acpi_driver_data(device); + acpi_device_remove_event_handler(device, ACPI_DEVICE_NOTIFY, acpi_fujitsu_laptop_notify); + fujitsu_laptop_platform_remove(device); kfifo_free(&priv->fifo); @@ -889,51 +944,6 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device) } } -static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event) -{ - struct fujitsu_laptop *priv = acpi_driver_data(device); - unsigned long flags; - int scancode, i = 0; - unsigned int irb; - - if (event != ACPI_FUJITSU_NOTIFY_CODE) { - acpi_handle_info(device->handle, "Unsupported event [0x%x]\n", - event); - sparse_keymap_report_event(priv->input, -1, 1, true); - return; - } - - if (priv->flags_supported) - priv->flags_state = call_fext_func(device, FUNC_FLAGS, 0x4, 0x0, - 0x0); - - while ((irb = call_fext_func(device, - FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 && - i++ < MAX_HOTKEY_RINGBUFFER_SIZE) { - scancode = irb & 0x4ff; - if (sparse_keymap_entry_from_scancode(priv->input, scancode)) - acpi_fujitsu_laptop_press(device, scancode); - else if (scancode == 0) - acpi_fujitsu_laptop_release(device); - else - acpi_handle_info(device->handle, - "Unknown GIRB result [%x]\n", irb); - } - - /* - * First seen on the Skylake-based Lifebook E736/E746/E756), the - * touchpad toggle hotkey (Fn+F4) is handled in software. Other models - * have since added additional "soft keys". These are reported in the - * status flags queried using FUNC_FLAGS. - */ - if (priv->flags_supported & (FLAG_SOFTKEYS)) { - flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0); - flags &= (FLAG_SOFTKEYS); - for_each_set_bit(i, &flags, BITS_PER_LONG) - sparse_keymap_report_event(priv->input, BIT(i), 1, true); - } -} - /* Initialization */ static const struct acpi_device_id fujitsu_bl_device_ids[] = { @@ -963,7 +973,6 @@ static struct acpi_driver acpi_fujitsu_laptop_driver = { .ops = { .add = acpi_fujitsu_laptop_add, .remove = acpi_fujitsu_laptop_remove, - .notify = acpi_fujitsu_laptop_notify, }, }; -- 2.40.1