Commit 5e2a55f2 authored by Alan Stern's avatar Alan Stern Committed by Jiri Kosina

USB HID: fix retry & reset logic

The USB HID driver fails to reset its error-retry timeout when there
has been a long time interval between I/O errors with no successful URB
completions in the meantime.  As a result, the very next error would
trigger an immediate reset, even if it was a chance event occurring
long after the previous error.

More USB keyboards and mice than one might expect end up getting I/O
errors. Almost always this results from hardware problems of one sort of
another. For example, people attach the device to a USB extension cable,
which degrades the signal.  Or they simply have poor quality cables to
begin with. Or they use a KVM switch which doesn't handle USB messages
correctly. Etc...

There have been reports from several users in which these I/O
errors would occur more or less randomly, at intervals ranging from
seconds to minutes.  The error-handling code in hid-core.c was originally
meant for situations where a single outage would persist for a few hundred
ms (electromagnetic interference, for example).  It didn't work right when
these more sporadic errors occurred, because of a flaw in the logic
which this patch fixes.

This patch (as873) fixes that oversight.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 48b4554a
...@@ -554,6 +554,11 @@ static void hid_io_error(struct hid_device *hid) ...@@ -554,6 +554,11 @@ static void hid_io_error(struct hid_device *hid)
if (usb_get_intfdata(usbhid->intf) == NULL) if (usb_get_intfdata(usbhid->intf) == NULL)
goto done; goto done;
/* If it has been a while since the last error, we'll assume
* this a brand new error and reset the retry timeout. */
if (time_after(jiffies, usbhid->stop_retry + HZ/2))
usbhid->retry_delay = 0;
/* When an error occurs, retry at increasing intervals */ /* When an error occurs, retry at increasing intervals */
if (usbhid->retry_delay == 0) { if (usbhid->retry_delay == 0) {
usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment