lkml.org 
[lkml]   [2001]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: PROBLEM: usb not working with 2.4.8-ac8
The usb-uhci and ohci worked fine, so I poked uhci a little bit
and made it all work, at least with my setup. Apparently,
sometimes uhci returns a success (0) from submit_urb, but
forgets to deliver a completion callback.

The fix is a Johannes' territory and I not so sure of my way there,
so perhaps a better one may be forthcoming.

I left the diagnostic printout in for usb_start_wait_urb,
we may drop it later. It must not be triggered if everything
works as planned.

-- Pete

diff -ur -X dontdiff linux-2.4.8-ac9/drivers/usb/uhci.c linux-2.4.8-ac9-niph/drivers/usb/uhci.c
--- linux-2.4.8-ac9/drivers/usb/uhci.c Wed Aug 22 11:01:57 2001
+++ linux-2.4.8-ac9-niph/drivers/usb/uhci.c Wed Aug 22 13:25:00 2001
@@ -1471,6 +1471,7 @@

static int uhci_submit_urb(struct urb *urb)
{
+ struct usb_device *dev;
int ret = -EINVAL;
struct uhci *uhci;
unsigned long flags;
@@ -1480,15 +1481,16 @@
if (!urb)
return -EINVAL;

- if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
+ dev = urb->dev;
+ if (!dev || !dev->bus || !dev->bus->hcpriv) {
warn("uhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
return -ENODEV;
}

- uhci = (struct uhci *)urb->dev->bus->hcpriv;
+ uhci = (struct uhci *)dev->bus->hcpriv;

INIT_LIST_HEAD(&urb->urb_list);
- usb_inc_dev_use(urb->dev);
+ usb_inc_dev_use(dev);

spin_lock_irqsave(&urb->lock, flags);

@@ -1497,7 +1499,7 @@
dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status);
/* Since we can have problems on the out path */
spin_unlock_irqrestore(&urb->lock, flags);
- usb_dec_dev_use(urb->dev);
+ usb_dec_dev_use(dev);

return ret;
}
@@ -1516,7 +1518,7 @@
}

/* Short circuit the virtual root hub */
- if (urb->dev == uhci->rh.dev) {
+ if (dev == uhci->rh.dev) {
ret = rh_submit_urb(urb);

goto out;
@@ -1528,13 +1530,13 @@
break;
case PIPE_INTERRUPT:
if (urb->bandwidth == 0) { /* not yet checked/allocated */
- bustime = usb_check_bandwidth(urb->dev, urb);
+ bustime = usb_check_bandwidth(dev, urb);
if (bustime < 0)
ret = bustime;
else {
ret = uhci_submit_interrupt(urb);
if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+ usb_claim_bandwidth(dev, urb, bustime, 0);
}
} else /* bandwidth is already set */
ret = uhci_submit_interrupt(urb);
@@ -1548,7 +1550,7 @@
ret = -EINVAL;
break;
}
- bustime = usb_check_bandwidth(urb->dev, urb);
+ bustime = usb_check_bandwidth(dev, urb);
if (bustime < 0) {
ret = bustime;
break;
@@ -1556,7 +1558,7 @@

ret = uhci_submit_isochronous(urb);
if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+ usb_claim_bandwidth(dev, urb, bustime, 1);
} else /* bandwidth is already set */
ret = uhci_submit_isochronous(urb);
break;
@@ -1578,8 +1580,14 @@

uhci_unlink_generic(uhci, urb);
uhci_destroy_urb_priv(urb);
+ if (ret == 0) { /* N.B. Done, must notify */
+ /* uhci_call_completion(urb); */ /* ->> uhci_destroy_urb_priv */
+ urb->dev = NULL;
+ if (urb->complete)
+ urb->complete(urb);
+ }

- usb_dec_dev_use(urb->dev);
+ usb_dec_dev_use(dev);

return ret;
}
diff -ur -X dontdiff linux-2.4.8-ac9/drivers/usb/usb.c linux-2.4.8-ac9-niph/drivers/usb/usb.c
--- linux-2.4.8-ac9/drivers/usb/usb.c Wed Aug 22 11:01:57 2001
+++ linux-2.4.8-ac9-niph/drivers/usb/usb.c Wed Aug 22 11:41:04 2001
@@ -1085,10 +1085,17 @@
set_current_state(TASK_RUNNING);
remove_wait_queue(&awd.wqh, &wait);

- if (!timeout && !awd.done) {
- printk("usb_control/bulk_msg: timeout\n");
- usb_unlink_urb(urb); // remove urb safely
- status = -ETIMEDOUT;
+ if (!awd.done) {
+ if (urb->status != -EINPROGRESS) { /* No callback?!! */
+ printk(KERN_ERR "usb: raced timeout, "
+ "pipe 0x%x status %d time left %d\n",
+ urb->pipe, urb->status, timeout);
+ status = urb->status;
+ } else {
+ printk("usb_control/bulk_msg: timeout\n");
+ usb_unlink_urb(urb); // remove urb safely
+ status = -ETIMEDOUT;
+ }
} else
status = urb->status;

@@ -1111,16 +1118,15 @@
urb = usb_alloc_urb(0);
if (!urb)
return -ENOMEM;
-
- FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, /* build urb */
- (usb_complete_t)usb_api_blocking_completion,0);
+
+ FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
+ usb_api_blocking_completion, 0);

retv = usb_start_wait_urb(urb, timeout, &length);
if (retv < 0)
return retv;
else
return length;
-
}

/**
@@ -1201,8 +1207,8 @@
if (!urb)
return -ENOMEM;

- FILL_BULK_URB(urb,usb_dev,pipe,(unsigned char*)data,len, /* build urb */
- (usb_complete_t)usb_api_blocking_completion,0);
+ FILL_BULK_URB(urb, usb_dev, pipe, data, len,
+ usb_api_blocking_completion, 0);

return usb_start_wait_urb(urb,timeout,actual_length);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:58    [W:0.061 / U:0.304 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site