diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-03-20 14:03:31 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2007-04-11 04:36:02 -0400 |
commit | 5e2a55f25d255a356bdaf2cb04c71b8d76c307a8 (patch) | |
tree | 70321ca66f373922bb722f81b315e08b510a826d /drivers/hid | |
parent | 48b4554aca28f721d3dfbab077c05032b3d1cd31 (diff) |
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: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 7c0fc11e972a..35a41e60f541 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -554,6 +554,11 @@ static void hid_io_error(struct hid_device *hid) | |||
554 | if (usb_get_intfdata(usbhid->intf) == NULL) | 554 | if (usb_get_intfdata(usbhid->intf) == NULL) |
555 | goto done; | 555 | goto done; |
556 | 556 | ||
557 | /* If it has been a while since the last error, we'll assume | ||
558 | * this a brand new error and reset the retry timeout. */ | ||
559 | if (time_after(jiffies, usbhid->stop_retry + HZ/2)) | ||
560 | usbhid->retry_delay = 0; | ||
561 | |||
557 | /* When an error occurs, retry at increasing intervals */ | 562 | /* When an error occurs, retry at increasing intervals */ |
558 | if (usbhid->retry_delay == 0) { | 563 | if (usbhid->retry_delay == 0) { |
559 | usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ | 564 | usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ |