ChangeSet 1.1305.7.3, 2003/06/13 16:41:08-07:00, [EMAIL PROTECTED]

[PATCH] USB:  ehci-hcd: short reads, chip workaround, cleanup

This is a minor update to the patch I posted the other day:

  - Updates processing for completed QTDs, fixing a regression
    I've been chasing for a while.

  - Works around a bug seen in some EHCI silicon (like NEC),
    which the previous problem was covering up.

  - Cleanup: updates the debug support a bit, removes a
    now-fixed FIXME comment, etc; and a version ID change.


 drivers/usb/host/ehci-dbg.c |   48 ++++++++++++++++++++++++++++----------------
 drivers/usb/host/ehci-hcd.c |   14 +++++-------
 drivers/usb/host/ehci-q.c   |   28 +++++++++++--------------
 drivers/usb/host/ehci.h     |    5 +++-
 4 files changed, 53 insertions(+), 42 deletions(-)


diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c       Wed Jun 18 11:16:05 2003
+++ b/drivers/usb/host/ehci-dbg.c       Wed Jun 18 11:16:05 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;
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c       Wed Jun 18 11:16:05 2003
+++ b/drivers/usb/host/ehci-hcd.c       Wed Jun 18 11:16:05 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-12"
 #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));
 
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Wed Jun 18 11:16:05 2003
+++ b/drivers/usb/host/ehci-q.c Wed Jun 18 11:16:05 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,7 +357,9 @@
        qh->qh_state = state;
 
        /* update qh after fault cleanup */
-       if (unlikely ((HALT_BIT & qh->hw_token) != 0)) {
+       if (unlikely (stopped != 0)
+                       /* some EHCI 0.95 impls will overlay dummy qtds */ 
+                       || qh->hw_qtd_next == EHCI_LIST_END) {
                qh_update (ehci, qh,
                        list_empty (&qh->qtd_list)
                                ? qh->dummy
@@ -787,11 +788,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,
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h   Wed Jun 18 11:16:05 2003
+++ b/drivers/usb/host/ehci.h   Wed Jun 18 11:16:05 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)
 
 /*-------------------------------------------------------------------------*/
 



-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to