[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#314954: [Linux-usb-users] Re: logitech usb mouse "dies"




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);

Reply to: