Yes indeed. This looks very similar to the problem reported in
http://bugzilla.kernel.org/show_bug.cgi?id=4916
See especially comment #19.
It's possible that the patch adding an HID reset routine (the last
attachment in the bug report) will work for you. You might have to fiddle
with it a little, because it is now four months old.
Yes, it works. No more freezing mouse despite the cold weather outside :-)
This _should_ have shown up in the dmesg log if you had CONFIG_USB_DEBUG
turned on. Make sure you have it on when running more tests.
Do you mean, it should have shown up without this patch? Since you told
me to enable CONFIG_USB_DEBUG, I had it always on while testing, but I
never saw that messages. Or do you mean, it is bug that these messages
weren't reported when CONFIG_USB_DEBUG is on?
The last 4 kernel messages since the first boot with your patch:
Dec 17 20:50:30 . kernel: mtrr: 0xe8000000,0x8000000 overlaps existing
0xe8000000,0x1000000
Dec 17 21:01:25 . kernel: drivers/usb/input/hid-core.c: input irq status
-84 received
Dec 17 21:25:43 . kernel: drivers/usb/input/hid-core.c: input irq status
-84 received
Dec 17 21:29:56 . kernel: drivers/usb/input/hid-core.c: input irq status
-84 received
I'm CCing Helmut Zeisel, he reported the same issue in an austrian
newsgroup. Helmut, you might want to try attached patch to fix our
"dying mouse" issue.
Willi
--- hid.h.bak 2005-12-17 20:25:41.000000000 +0100
+++ hid.h 2005-12-17 21:12:07.000000000 +0100
@@ -396,6 +396,8 @@
struct urb *urbin; /* Input URB */
char *inbuf; /* Input buffer */
dma_addr_t inbuf_dma; /* Input buffer dma */
+ int in_error_cnt; /* Input error counter */
+ struct work_struct work; /* Perform asynchronous reset */
struct urb *urbctrl; /* Control URB */
struct usb_ctrlrequest *cr; /* Control request struct */
--- hid-core.c.bak 2005-12-17 20:26:53.000000000 +0100
+++ hid-core.c 2005-12-17 20:31:41.000000000 +0100
@@ -909,6 +909,29 @@
}
/*
+ * Request a device reset.
+ */
+static void hid_reset(void *_hid)
+{
+ struct hid_device *hid = _hid;
+ int rc, result;
+
+ hid->in_error_cnt = 0;
+ rc = result = usb_lock_device_for_reset(hid->dev, hid->intf);
+ if (rc >= 0) {
+ result = usb_reset_device(hid->dev);
+ if (result == 0 && hid->open)
+ result = usb_submit_urb(hid->urbin, GFP_NOIO);
+ if (rc)
+ usb_unlock_device(hid->dev);
+ }
+ if (result < 0)
+ warn("can't reset device, %s-%s/input%d, result %d",
+ hid->dev->bus->bus_name, hid->dev->devpath,
+ hid->ifnum, result);
+}
+
+/*
* Input interrupt completion handler.
*/
@@ -919,18 +942,20 @@
switch (urb->status) {
case 0: /* success */
+ hid->in_error_cnt = 0;
hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -EPERM:
case -ESHUTDOWN: /* unplug */
- case -EILSEQ: /* unplug timeout on uhci */
return;
- case -ETIMEDOUT: /* NAK */
- break;
default: /* error */
warn("input irq status %d received", urb->status);
+ if (++hid->in_error_cnt >= 10) {
+ schedule_work(&hid->work);
+ return;
+ }
}
status = usb_submit_urb(urb, SLAB_ATOMIC);
@@ -1099,7 +1124,6 @@
case 0: /* success */
break;
case -ESHUTDOWN: /* unplug */
- case -EILSEQ: /* unplug timeout on uhci */
unplug = 1;
case -ECONNRESET: /* unlink */
case -ENOENT:
@@ -1147,7 +1171,6 @@
hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
break;
case -ESHUTDOWN: /* unplug */
- case -EILSEQ: /* unplug timectrl on uhci */
unplug = 1;
case -ECONNRESET: /* unlink */
case -ENOENT:
@@ -1781,6 +1804,7 @@
hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ INIT_WORK(&hid->work, hid_reset, hid);
return hid;
fail:
@@ -1808,6 +1832,7 @@
usb_kill_urb(hid->urbin);
usb_kill_urb(hid->urbout);
usb_kill_urb(hid->urbctrl);
+ flush_scheduled_work();
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);