Major A wrote:
This patch brings the 2.4.21-rc8 EHCI driver mostly back
into sync with the latest 2.5 driver (*), and adds a patch
to avoid a relink problem (symptoms: rx hang, tx overflow)
which causes trouble on 2.4 (especially with usb-storage).


Just tried (patched 2.4.21 with it) with the hard drive, it really
does the same as 2.5.70-bk8 with your earlier patch (ehci-0609.patch):
it hangs.

The last 2.5 patch was ehci-0612, and it had key differences from 0609 that affected problems I saw on NEC hardware, which you were using. (You never tested 0610...) Attached, you'll see ohci-0613, which should be just 0612 with that relink fix.


Let me know if I can do some more testing.

At least provide a good description of your _current_ failure mode. Doing it on 2.5 with the sysfs dumps would be most useful, also answering all the usual questions about what exactly hangs, and how. Descriptions like "it hangs" are pretty useless.

- Dave


--- 1.32/drivers/usb/host/ehci-dbg.c    Mon Mar 24 16:03:55 2003
+++ edited/drivers/usb/host/ehci-dbg.c  Fri Jun 13 12:40:31 2003
@@ -115,19 +115,28 @@
 #ifdef DEBUG
 
 static void __attribute__((__unused__))
+dbg_qtd (char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+{
+       ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+               cpu_to_le32p (&qtd->hw_next),
+               cpu_to_le32p (&qtd->hw_alt_next),
+               cpu_to_le32p (&qtd->hw_token),
+               cpu_to_le32p (&qtd->hw_buf [0]));
+       if (qtd->hw_buf [1])
+               ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
+                       cpu_to_le32p (&qtd->hw_buf [1]),
+                       cpu_to_le32p (&qtd->hw_buf [2]),
+                       cpu_to_le32p (&qtd->hw_buf [3]),
+                       cpu_to_le32p (&qtd->hw_buf [4]));
+}
+
+static void __attribute__((__unused__))
 dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       dbg ("%s %p n%08x info1 %x info2 %x hw_curr %x qtd_next %x", label,
+       ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
                qh, qh->hw_next, qh->hw_info1, qh->hw_info2,
-               qh->hw_current, qh->hw_qtd_next);
-       dbg ("  alt+nak+t= %x, token= %x, page0= %x, page1= %x",
-               qh->hw_alt_next, qh->hw_token,
-               qh->hw_buf [0], qh->hw_buf [1]);
-       if (qh->hw_buf [2]) {
-               dbg ("  page2= %x, page3= %x, page4= %x",
-                       qh->hw_buf [2], qh->hw_buf [3],
-                       qh->hw_buf [4]);
-       }
+               qh->hw_current);
+       dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next);
 }
 
 static int __attribute__((__unused__))
@@ -284,8 +293,7 @@
                return '*';
        if (token & QTD_STS_HALT)
                return '-';
-       if (QTD_PID (token) != 1 /* not IN: OUT or SETUP */
-                       || QTD_LENGTH (token) == 0)
+       if (!IS_SHORT_READ (token))
                return ' ';
        /* tries to advance through hw_alt_next */
        return '/';
@@ -307,11 +315,14 @@
        char                    *next = *nextp;
        char                    mark;
 
-       mark = token_mark (qh->hw_token);
+       if (qh->hw_qtd_next == EHCI_LIST_END)   /* NEC does this */
+               mark = '@';
+       else
+               mark = token_mark (qh->hw_token);
        if (mark == '/') {      /* qh_alt_next controls qh advance? */
                if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
                        mark = '#';     /* blocked */
-               else if (qh->hw_alt_next & cpu_to_le32 (0x01))
+               else if (qh->hw_alt_next == EHCI_LIST_END)
                        mark = '.';     /* use hw_qtd_next */
                /* else alt_next points to some other qtd */
        }
@@ -324,7 +335,7 @@
                        (scratch >> 8) & 0x000f,
                        scratch, cpu_to_le32p (&qh->hw_info2),
                        cpu_to_le32p (&qh->hw_token), mark,
-                       (cpu_to_le32 (0x8000000) & qh->hw_token)
+                       (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
                                ? "data0" : "data1",
                        (cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
        size -= temp;
@@ -390,6 +401,8 @@
        char                    *next;
        struct ehci_qh          *qh;
 
+       *buf = 0;
+
        pdev = container_of (dev, struct pci_dev, dev);
        ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
        next = buf;
@@ -412,7 +425,7 @@
        }
        spin_unlock_irqrestore (&ehci->lock, flags);
 
-       return PAGE_SIZE - size;
+       return strlen (buf);
 }
 static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
@@ -548,7 +561,8 @@
        /* Capability Registers */
        i = readw (&ehci->caps->hci_version);
        temp = snprintf (next, size,
-               "EHCI %x.%02x, hcd state %d (version " DRIVER_VERSION ")\n",
+               "%s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n",
+               pdev->dev.name,
                i >> 8, i & 0x0ff, ehci->hcd.state);
        size -= temp;
        next += temp;
--- 1.82/drivers/usb/host/ehci-hcd.c    Thu May 29 00:55:47 2003
+++ edited/drivers/usb/host/ehci-hcd.c  Fri Jun 13 14:39:58 2003
@@ -39,13 +39,10 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/usb.h>
+#include <linux/moduleparam.h>
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32)
-#include "../hcd.h"
-#else
 #include "../core/hcd.h"
-#endif
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -94,11 +91,11 @@
  * 2001-June   Works with usb-storage and NEC EHCI on 2.4
  */
 
-#define DRIVER_VERSION "2003-Jan-22"
+#define DRIVER_VERSION "2003-Jun-13"
 #define DRIVER_AUTHOR "David Brownell"
 #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
 
-static const char      hcd_name [] = "ehci-hcd";
+static const char      hcd_name [] = "ehci_hcd";
 
 
 // #define EHCI_VERBOSE_DEBUG
@@ -123,7 +120,7 @@
 
 /* Initial IRQ latency:  lower than default */
 static int log2_irq_thresh = 0;                // 0 to 6
-MODULE_PARM (log2_irq_thresh, "i");
+module_param (log2_irq_thresh, int, S_IRUGO);
 MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
 
 #define        INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT)
@@ -1020,7 +1017,8 @@
        if (usb_disabled())
                return -ENODEV;
 
-       dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd",
+       pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+               hcd_name,
                sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
                sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
 
--- 1.76/drivers/usb/host/ehci-q.c      Thu May 29 00:55:48 2003
+++ edited/drivers/usb/host/ehci-q.c    Fri Jun 13 12:41:09 2003
@@ -88,7 +88,6 @@
 static inline void
 qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 {
-       qh->hw_current = 0;
        qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
        qh->hw_alt_next = EHCI_LIST_END;
 
@@ -99,8 +98,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
-
 static void qtd_copy_status (
        struct ehci_hcd *ehci,
        struct urb *urb,
@@ -279,16 +276,15 @@
                /* hardware copies qtd out of qh overlay */
                rmb ();
                token = le32_to_cpu (qtd->hw_token);
-               stopped = stopped
-                       || (HALT_BIT & qh->hw_token) != 0
-                       || (ehci->hcd.state == USB_STATE_HALT);
 
                /* always clean up qtds the hc de-activated */
                if ((token & QTD_STS_ACTIVE) == 0) {
 
-                       /* magic dummy for short reads; won't advance */
-                       if (IS_SHORT_READ (token)
-                                       && !(token & QTD_STS_HALT)
+                       if ((token & QTD_STS_HALT) != 0) {
+                               stopped = 1;
+
+                       /* magic dummy for some short reads; qh won't advance */
+                       } else if (IS_SHORT_READ (token)
                                        && (qh->hw_alt_next & QTD_MASK)
                                                == ehci->async->hw_alt_next) {
                                stopped = 1;
@@ -296,10 +292,13 @@
                        }
 
                /* stop scanning when we reach qtds the hc is using */
-               } else if (likely (!stopped)) {
+               } else if (likely (!stopped
+                               || HCD_IS_RUNNING (ehci->hcd.state))) {
                        break;
 
                } else {
+                       stopped = 1;
+
                        /* ignore active urbs unless some previous qtd
                         * for the urb faulted (including short read) or
                         * its urb was canceled.  we may patch qh or qtds.
@@ -358,12 +357,20 @@
        qh->qh_state = state;
 
        /* update qh after fault cleanup */
-       if (unlikely ((HALT_BIT & qh->hw_token) != 0)) {
-               qh_update (ehci, qh,
-                       list_empty (&qh->qtd_list)
-                               ? qh->dummy
-                               : list_entry (qh->qtd_list.next,
-                                       struct ehci_qtd, qtd_list));
+       if (unlikely (stopped != 0)
+                       /* some EHCI 0.95 impls will overlay dummy qtds */ 
+                       || qh->hw_qtd_next == EHCI_LIST_END) {
+               if (list_empty (&qh->qtd_list))
+                       end = qh->dummy;
+               else {
+                       end = list_entry (qh->qtd_list.next,
+                                       struct ehci_qtd, qtd_list);
+                       /* first qtd may already be partially processed */
+                       if (cpu_to_le32 (end->qtd_dma) == qh->hw_current)
+                               end = 0;
+               }
+               if (end)
+                       qh_update (ehci, qh, end);
        }
 
        return count;
@@ -787,11 +794,6 @@
                                }
                        }
                }
-
-               /* FIXME:  changing config or interface setting is not
-                * supported yet.  preferred fix is for usbcore to tell
-                * us to clear out each endpoint's state, but...
-                */
 
                /* usb_clear_halt() means qh data toggle gets reset */
                if (unlikely (!usb_gettoggle (urb->dev,
--- 1.32/drivers/usb/host/ehci.h        Thu May 29 00:55:48 2003
+++ edited/drivers/usb/host/ehci.h      Fri Jun 13 12:40:31 2003
@@ -290,7 +290,10 @@
        size_t                  length;                 /* length of buffer */
 } __attribute__ ((aligned (32)));
 
-#define QTD_MASK cpu_to_le32 (~0x1f)   /* mask NakCnt+T in qh->hw_alt_next */
+/* mask NakCnt+T in qh->hw_alt_next */
+#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+
+#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
 
 /*-------------------------------------------------------------------------*/
 

Reply via email to