Hi, David:
I had a few folks complaining that ehci in 2.4 hangs. While we tried to
address that in 2.4.29, I heard complains of regressions (ok, just one
regression - from Michael). Still, I guess the only way now is forward.
Thus, the next step is the unlink_async. Surprisingly, it looks too easy.
Do you happen to remember if this is all that it took to add unlink_async?
The patch adds Brian's fix. Is anyone up for testing?
Thanks,
-- Pete
diff -urp -X dontdiff linux-2.4.31/drivers/usb/host/ehci-hcd.c
linux-2.4.31-usb/drivers/usb/host/ehci-hcd.c
--- linux-2.4.31/drivers/usb/host/ehci-hcd.c 2004-11-22 23:04:18.000000000
-0800
+++ linux-2.4.31-usb/drivers/usb/host/ehci-hcd.c 2005-06-28
17:23:12.000000000 -0700
@@ -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.31/drivers/usb/host/ehci-q.c
linux-2.4.31-usb/drivers/usb/host/ehci-q.c
--- linux-2.4.31/drivers/usb/host/ehci-q.c 2005-01-25 11:17:24.000000000
-0800
+++ linux-2.4.31-usb/drivers/usb/host/ehci-q.c 2005-06-28 17:33:13.000000000
-0700
@@ -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 +429,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 */
}
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel