On Thu, 6 Oct 2005 16:43:44 -0400 (EDT), Alan Stern <[EMAIL PROTECTED]> wrote:
> This patch (as576) removes some mistaken tests for disconnection from the
> HID driver. -EILSEQ refers to an arbitrary low-level protocol error, not
> necessarily a disconnection. Also, a completion routine will never see a
> status of -EPERM; that's used only to indicate a failure during
> usb_submit_urb.
> --- usb-2.6.orig/drivers/usb/input/hid-core.c
> +++ usb-2.6/drivers/usb/input/hid-core.c
> @@ -923,9 +923,7 @@ static void hid_irq_in(struct urb *urb,
> break;
> case -ECONNRESET: /* unlink */
> case -ENOENT:
> - case -EPERM:
> case -ESHUTDOWN: /* unplug */
> - case -EILSEQ: /* unplug timeout on uhci */
> return;
> case -ETIMEDOUT: /* NAK */
> break;
No freaking way, man. Is there a particular scenario which this patch
fixes? Because that code is there for a reason. You cannot just do
it because some retarded document in Documentation/ suggests that it
might be a good idea.
I have a bug assigned (bz#167070), which is, unfortunately, private.
But the summary goes like this
HID driver completion handler prints -84(-EILSEQ) error messages
when a USB keyboard or mouse was unplugged.
When a USB keyboard or mouse was unplugged,
HID driver completion handler hid_irq_in() (@drivers/usb/input/hid-core.c)
continuously prints an error message "input irq status -84 received".
Once the USB was unplugged, the machine just hungs up.
By the way, I have already found the patch to fix this
problem at http://lkml.org/lkml/2005/1/27/176.
The problem was settled by applying this patch to
drivers/usb/input/hid-core.c.
Attached is a patch we may be shipping as a hotfix for RHEL 4 U2 and
which is going to be shipped in U3 by normal means.
I can guarantee you Vojtech and Greg see the same with SLES.
On RHEL 3 I had the same problem, and there we cannot officially
rely on error code. But any driver which submits interrupt URBs
has to handle this correctly. Check this (it's MCT_U232, but HID
is exactly the same):
http://lwn.net/Articles/123025/
-- Pete
diff -urp -X dontdiff linux-2.6.9-16.EL/drivers/usb/input/hid-core.c
linux-2.6.9-16.EL.z1/drivers/usb/input/hid-core.c
--- linux-2.6.9-16.EL/drivers/usb/input/hid-core.c 2005-08-16
18:27:59.000000000 -0700
+++ linux-2.6.9-16.EL.z1/drivers/usb/input/hid-core.c 2005-09-01
23:51:32.000000000 -0700
@@ -918,14 +918,26 @@ static void hid_irq_in(struct urb *urb,
struct hid_device *hid = urb->context;
int status;
+ if (urb->status == -EILSEQ) { /* unplug (on uhci) or other error */
+ if (hid->error_count >= 2) {
+ info("not resubmitting, input%d", hid->ifnum);
+ return;
+ }
+ hid->error_count++;
+ } else {
+ hid->error_count = 0;
+ }
+
switch (urb->status) {
case 0: /* success */
hid_input_report(HID_INPUT_REPORT, urb, regs);
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
- case -ESHUTDOWN:
+ case -EPERM:
+ case -ESHUTDOWN: /* unplug */
return;
+ case -EILSEQ:
case -ETIMEDOUT: /* NAK */
break;
default: /* error */
@@ -1134,12 +1146,15 @@ static void hid_irq_out(struct urb *urb,
{
struct hid_device *hid = urb->context;
unsigned long flags;
+ int unplug = 0;
switch (urb->status) {
case 0: /* success */
+ case -ESHUTDOWN: /* unplug */
+ case -EILSEQ: /* unplug timeout on uhci */
+ unplug = 1;
case -ECONNRESET: /* unlink */
case -ENOENT:
- case -ESHUTDOWN:
break;
default: /* error */
warn("output irq status %d received", urb->status);
@@ -1147,7 +1162,10 @@ static void hid_irq_out(struct urb *urb,
spin_lock_irqsave(&hid->outlock, flags);
- hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ if (unplug)
+ hid->outtail = hid->outhead;
+ else
+ hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
if (hid->outhead != hid->outtail) {
if (hid_submit_out(hid)) {
@@ -1171,6 +1189,7 @@ static void hid_ctrl(struct urb *urb, st
{
struct hid_device *hid = urb->context;
unsigned long flags;
+ int unplug = 0;
spin_lock_irqsave(&hid->ctrllock, flags);
@@ -1178,16 +1197,21 @@ static void hid_ctrl(struct urb *urb, st
case 0: /* success */
if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+ case -ESHUTDOWN: /* unplug */
+ case -EILSEQ: /* unplug timectrl on uhci */
+ unplug = 1;
case -ECONNRESET: /* unlink */
case -ENOENT:
- case -ESHUTDOWN:
case -EPIPE: /* report not available */
break;
default: /* error */
warn("ctrl urb status %d received", urb->status);
}
- hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ if (unplug)
+ hid->ctrltail = hid->ctrlhead;
+ else
+ hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE -
1);
if (hid->ctrlhead != hid->ctrltail) {
if (hid_submit_ctrl(hid)) {
diff -urp -X dontdiff linux-2.6.9-16.EL/drivers/usb/input/hid.h
linux-2.6.9-16.EL.z1/drivers/usb/input/hid.h
--- linux-2.6.9-16.EL/drivers/usb/input/hid.h 2004-10-18 14:53:06.000000000
-0700
+++ linux-2.6.9-16.EL.z1/drivers/usb/input/hid.h 2005-09-01
22:26:57.000000000 -0700
@@ -382,6 +382,8 @@ struct hid_device {
/* device repo
char phys[64]; /*
Device physical location */
char uniq[64]; /*
Device unique identifier (serial #) */
+ int error_count;
+
void *ff_private; /*
Private data for the force-feedback driver */
void (*ff_exit)(struct hid_device*); /*
Called by hid_exit_ff(hid) */
int (*ff_event)(struct hid_device *hid, struct input_dev *input,
-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel