This is a long-standing problem. I had people hitting it from time to time,
but they would always go under instead of testing and reporting. Now one
gentleman reports stepping on this bug under simpler to reproduce conditions
than before. In his case, I/O stops when two DVD drives are connected
to the same bus.
I would like this to be in a test release after 2.4.32.
-- Pete
diff -urp -X dontdiff linux-2.4.32.patched/drivers/usb/host/ehci-hcd.c
linux-2.4.32-wk/drivers/usb/host/ehci-hcd.c
--- linux-2.4.32.patched/drivers/usb/host/ehci-hcd.c 2004-11-22
23:04:18.000000000 -0800
+++ linux-2.4.32-wk/drivers/usb/host/ehci-hcd.c 2005-12-15 13:59:50.000000000
-0800
@@ -796,6 +796,30 @@ static int ehci_urb_enqueue (
}
}
+static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ /* if we need to use IAA and it's busy, defer */
+ if (qh->qh_state == QH_STATE_LINKED
+ && ehci->reclaim
+ && HCD_IS_RUNNING (ehci->hcd.state)) {
+ struct ehci_qh *last;
+
+ for (last = ehci->reclaim;
+ last->reclaim;
+ last = last->reclaim)
+ continue;
+ qh->qh_state = QH_STATE_UNLINK_WAIT;
+ last->reclaim = qh;
+
+ /* bypass IAA if the hc can't care */
+ } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim)
+ end_unlink_async (ehci, NULL);
+
+ /* something else might have unlinked the qh by now */
+ if (qh->qh_state == QH_STATE_LINKED)
+ start_unlink_async (ehci, qh);
+}
+
/* remove from hardware lists
* completions normally happen asynchronously
*/
@@ -814,28 +838,7 @@ static int ehci_urb_dequeue (struct usb_
qh = (struct ehci_qh *) urb->hcpriv;
if (!qh)
break;
-
- /* if we need to use IAA and it's busy, defer */
- if (qh->qh_state == QH_STATE_LINKED
- && ehci->reclaim
- && HCD_IS_RUNNING (ehci->hcd.state)
- ) {
- struct ehci_qh *last;
-
- for (last = ehci->reclaim;
- last->reclaim;
- last = last->reclaim)
- continue;
- qh->qh_state = QH_STATE_UNLINK_WAIT;
- last->reclaim = qh;
-
- /* bypass IAA if the hc can't care */
- } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim)
- end_unlink_async (ehci, NULL);
-
- /* something else might have unlinked the qh by now */
- if (qh->qh_state == QH_STATE_LINKED)
- start_unlink_async (ehci, qh);
+ unlink_async (ehci, qh);
break;
case PIPE_INTERRUPT:
diff -urp -X dontdiff linux-2.4.32.patched/drivers/usb/host/ehci-q.c
linux-2.4.32-wk/drivers/usb/host/ehci-q.c
--- linux-2.4.32.patched/drivers/usb/host/ehci-q.c 2005-01-25
11:17:24.000000000 -0800
+++ linux-2.4.32-wk/drivers/usb/host/ehci-q.c 2005-12-15 13:59:50.000000000
-0800
@@ -199,8 +199,6 @@ ehci_urb_done (struct ehci_hcd *ehci, st
#ifdef INTR_AUTOMAGIC
struct urb *resubmit = 0;
struct usb_device *dev = 0;
-
- static int ehci_urb_enqueue (struct usb_hcd *, struct urb *, int);
#endif
if (likely (urb->hcpriv != 0)) {
@@ -280,6 +278,7 @@ ehci_urb_done (struct ehci_hcd *ehci, st
}
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
+static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
/*
* Process and free completed qtds for a qh, returning URBs to drivers.
@@ -430,7 +430,7 @@ halt:
qh_refresh(ehci, qh);
break;
case QH_STATE_LINKED:
- start_unlink_async (ehci, qh);
+ unlink_async (ehci, qh);
break;
/* otherwise, unlink already started */
}
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel