add backported usb2 fix from 2.4.33-pre1
authorFelix Fietkau <nbd@openwrt.org>
Tue, 31 Jan 2006 11:42:49 +0000 (11:42 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 31 Jan 2006 11:42:49 +0000 (11:42 +0000)
SVN-Revision: 3080

openwrt/target/linux/linux-2.4/patches/generic/212-usb_ehci_fix.patch [new file with mode: 0644]

diff --git a/openwrt/target/linux/linux-2.4/patches/generic/212-usb_ehci_fix.patch b/openwrt/target/linux/linux-2.4/patches/generic/212-usb_ehci_fix.patch
new file mode 100644 (file)
index 0000000..f4ec141
--- /dev/null
@@ -0,0 +1,93 @@
+diff -Nur linux-2.4.32/drivers/usb/host/ehci-hcd.c linux-2.4.33-pre1/drivers/usb/host/ehci-hcd.c
+--- linux-2.4.32/drivers/usb/host/ehci-hcd.c   2004-11-17 09:54:21.000000000 -0200
++++ linux-2.4.33-pre1/drivers/usb/host/ehci-hcd.c      2005-12-28 18:15:56.000000000 -0200
+@@ -796,6 +796,30 @@
+       }
+ }
++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 @@
+               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 -Nur linux-2.4.32/drivers/usb/host/ehci-q.c linux-2.4.33-pre1/drivers/usb/host/ehci-q.c
+--- linux-2.4.32/drivers/usb/host/ehci-q.c     2005-01-19 12:10:07.000000000 -0200
++++ linux-2.4.33-pre1/drivers/usb/host/ehci-q.c        2005-12-28 18:15:56.000000000 -0200
+@@ -199,8 +199,6 @@
+ #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 @@
+ }
+ 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 @@
+                       qh_refresh(ehci, qh);
+                       break;
+               case QH_STATE_LINKED:
+-                      start_unlink_async (ehci, qh);
++                      unlink_async (ehci, qh);
+                       break;
+               /* otherwise, unlink already started */
+               }