[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260208-usbhid-eproto-v1-1-5872c10d90bb@gmail.com>
Date: Sun, 08 Feb 2026 18:10:19 +0100
From: Liam Mitchell <mitchell.liam@...il.com>
To: Jiri Kosina <jikos@...nel.org>, Benjamin Tissoires <bentiss@...nel.org>
Cc: Alan Stern <stern@...land.harvard.edu>, linux-usb@...r.kernel.org,
linux-input@...r.kernel.org, linux-kernel@...r.kernel.org,
Liam Mitchell <mitchell.liam@...il.com>
Subject: [PATCH] usbhid: tolerate intermittent errors
Modifies the usbhid error handling logic to better handle intermittent
errors like EPROTO, which should only need resubmission of URBs and not
full device reset.
Reduces initial retry delay from 13ms to 1ms. The faster the URB is
resubmitted, the lower the chance that user events will be missed.
Increases retry delay multiplier from 2 to 5, reaching max delay in a
similar number of retries.
Adds another check to the reset block, only resetting if retry_delay has
reached max, effectively only allowing reset after 4 errors.
---
The usbhid driver will reset a device after only two errors 1-1.5s apart.
The first error will be handled with a retry after 13ms.
Handling of the second error depends on the time since the first:
* <1000ms: retry after 26ms
* >1000ms & <1500ms: reset USB device, taking maybe hundreds of ms
* >1500ms: retry after 13ms
It doesn't take into account the type, count or timing of errors.
EPROTO errors can occur randomly, sometimes frequently and are often not
fixed by a device reset.
Retry delays or device resets only raise the chance that input events will
be missed and that users see symptoms like missed or sticky keyboard keys.
See following thread for more details:
https://lore.kernel.org/linux-input/CAOQ1CL6Q+4GNy=kgisLzs0UBXFT3b02PG8t-0rPuW-Wf6NhQ6g@mail.gmail.com/
The following patch is a minimal change to better tolerate intermittent errors.
Using existing variables, we reduce initial retry delays and only reset in
the 1000-1500ms window if 4+ errors have occurred.
This should reduce issues for users with intermittent errors and retain
the intended retry-backoff-reset for erroring devices that need a reset.
More comprehensive error handling could involve counting errors, time between
errors and/or switching on error type but would be more invasive.
Signed-off-by: Liam Mitchell <mitchell.liam@...il.com>
---
drivers/hid/usbhid/hid-core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index aac0051a2cf6..b6e956ca781b 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -160,12 +160,12 @@ static void hid_io_error(struct hid_device *hid)
/* When an error occurs, retry at increasing intervals */
if (usbhid->retry_delay == 0) {
- usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
+ usbhid->retry_delay = 1; /* Then 5, 25, 125, 125, ... */
usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
} else if (usbhid->retry_delay < 100)
- usbhid->retry_delay *= 2;
+ usbhid->retry_delay *= 5;
- if (time_after(jiffies, usbhid->stop_retry)) {
+ if (time_after(jiffies, usbhid->stop_retry) && usbhid->retry_delay >= 100) {
/* Retries failed, so do a port reset unless we lack bandwidth*/
if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
---
base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
change-id: 20260208-usbhid-eproto-152c7abcb185
Best regards,
--
Liam Mitchell <mitchell.liam@...il.com>
Powered by blists - more mailing lists