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

Reply via email to