From 35f0a0dceddce3a6008a24716bd02766e511ae49 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 2 Aug 2026 17:52:01 -0700 Subject: Input: ensure device is ready before delivering events When a device is opened via input_open_device(), the driver's open() callback is invoked. Some drivers, like cm109, submit URBs or perform other hardware initialization in their open() callbacks. However, the input core does not prevent dev->event() from being called concurrently during the driver's open() execution. For instance, if a console beep occurs, the kbd handler might inject an EV_SND event. This can lead to double list_add BUGs if the driver submits the same URB in both open() and event() paths without adequate synchronization. To fix this, introduce a ready flag in the input_dev structure. For complex devices (where dev->open is defined), this flag is set to true only after the driver's open() method successfully completes. The core now checks ready in input_event_dispose() and input_dev_toggle() to prevent events from reaching the hardware before it is fully prepared. For simple devices (no open callback), events are delivered immediately. We also replay the logical state in input_open_device() by calling input_dev_toggle() right after marking the device ready, ensuring no events are permanently lost. In the inhibit path, we ensure that physical feedback (LEDs/sounds) is turned off before the device is closed, and we synchronize the inhibited state transition under the event lock to prevent races with incoming events. Assisted-by: Antigravity:gemini-3.5-flash Link: https://patch.msgid.link/20260803005210.1251102-1-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/input.h b/include/linux/input.h index 76f7aa226202..f147d27e6d1d 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -128,11 +128,14 @@ enum input_clock_type { * @devres_managed: indicates that devices is managed with devres framework * and needs not be explicitly unregistered or freed. * @timestamp: storage for a timestamp set by input_set_timestamp called - * by a driver + * by a driver * @inhibited: indicates that the input device is inhibited. If that is - * the case then input core ignores any events generated by the device. - * Device's close() is called when it is being inhibited and its open() - * is called when it is being uninhibited. + * the case then input core ignores any events generated by the device. + * Device's close() is called when it is being inhibited and its open() + * is called when it is being uninhibited. + * @ready: indicates that the device has been successfully opened and is + * prepared to process events (like LEDs or sounds) sent from the + * input core. */ struct input_dev { const char *name; @@ -209,6 +212,7 @@ struct input_dev { ktime_t timestamp[INPUT_CLK_MAX]; bool inhibited; + bool ready; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) -- cgit v1.2.3 From 876848ad2203d225e927a5f3373900bcbb73c9c5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 2 Aug 2026 17:52:04 -0700 Subject: Input: defer handler's start() until device is opened When registering an input handle, handler->start() is currently called immediately. However, the input device might not be fully opened or ready to process events at this stage, meaning any state synchronization events (like setting LED states) injected by the handler's start method might be dropped. Move the handler->start() invocation to input_open_device(). If it is the first handle opening the device, start() is called after the driver's open() method has successfully completed and the device is fully prepared. To facilitate this, factor out the device startup logic (calling driver's open and starting polling) into input_start_device(). For passive observer handlers, their start() method is also deferred until the handle is opened. Since opening a passive observer handle does not start the underlying hardware device, their start() method is called immediately upon opening, regardless of whether the device is active. Fixes: c7e8dc6ee6d5 ("Input: add start() method to input handlers") Link: https://patch.msgid.link/20260803005210.1251102-4-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/input.h b/include/linux/input.h index f147d27e6d1d..0ee5f32de08a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -288,8 +288,9 @@ struct input_handle; * @connect: called when attaching a handler to an input device * @disconnect: disconnects a handler from input device * @start: starts handler for given handle. This function is called by - * input core right after connect() method and also when a process - * that "grabbed" a device releases it + * input core when device is open and ready to process events, + * and also when device is uninhibited or when a process that "grabbed" + * a device releases it * @passive_observer: set to %true by drivers only interested in observing * data stream from devices if there are other users present. Such * drivers will not result in starting underlying hardware device -- cgit v1.2.3 From 8c3ff3164b6ec28f2977f71645a5e6d7fde06924 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 3 Aug 2026 16:48:11 -0700 Subject: Input: reject inhibit and uninhibit requests on unregistering devices When an input device is being unregistered via input_unregister_device(), input_disconnect_device() sets dev->going_away = true under dev->mutex and releases the mutex. If a concurrent sysfs write to the inhibited attribute executes input_inhibit_device() or input_uninhibit_device(), it acquires dev->mutex. Because neither function checks dev->going_away (unlike input_open_device()), input_uninhibit_device() proceeds to call dev->open() and start polling on a device that is in the middle of being unregistered and torn down. Fix this by checking dev->going_away in input_inhibit_device() and input_uninhibit_device() under dev->mutex and returning -ENODEV if the device is going away. Fixes: a181616487db ("Input: Add "inhibited" property") Reported-by: sashiko-bot@kernel.org Assisted-by: Antigravity:gemini-3.6-flash Link: https://patch.msgid.link/anEolqA35rGei9ql@google.com Signed-off-by: Dmitry Torokhov --- include/linux/input.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/input.h b/include/linux/input.h index 0ee5f32de08a..3381608127f7 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -117,7 +117,8 @@ enum input_clock_type { * user opens device and dev->close() is called when the very * last user closes the device * @going_away: marks devices that are in a middle of unregistering and - * causes input_open_device*() fail with -ENODEV. + * causes input_open_device() and input_inhibit/uninhibit_device() + * to fail with -ENODEV. * @dev: driver model's view of this device * @h_list: list of input handles associated with the device. When * accessing the list dev->mutex must be held -- cgit v1.2.3 From 785a490556b549493a6a25409f16026ce0959b02 Mon Sep 17 00:00:00 2001 From: Longlong Xia Date: Sun, 9 Aug 2026 22:29:28 +0800 Subject: Input: elan_i2c - use device-id/acpi.h for ACPI IDs elan-i2c-ids.h only needs struct acpi_device_id from the ACPI device ID definitions. The MODULE_DEVICE_TABLE() user already includes . Include instead of the broader header. Assisted-by: Codex:GPT-5 Signed-off-by: Longlong Xia Link: https://patch.msgid.link/20260809142928.4031270-1-xialonglong2025@163.com Signed-off-by: Dmitry Torokhov --- include/linux/input/elan-i2c-ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/input/elan-i2c-ids.h b/include/linux/input/elan-i2c-ids.h index 51cca17ee94c..874bf0ab500c 100644 --- a/include/linux/input/elan-i2c-ids.h +++ b/include/linux/input/elan-i2c-ids.h @@ -18,7 +18,7 @@ #ifndef __ELAN_I2C_IDS_H #define __ELAN_I2C_IDS_H -#include +#include static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0000", 0 }, -- cgit v1.2.3