USB: EHCI: check for STALL before other errors
[safe/jmp/linux-2.6] / drivers / usb / host / ehci-q.c
index e3d2b62..9a13847 100644 (file)
@@ -214,6 +214,14 @@ static int qtd_copy_status (
                if (token & QTD_STS_BABBLE) {
                        /* FIXME "must" disable babbling device's port too */
                        status = -EOVERFLOW;
+               /* CERR nonzero + halt --> stall */
+               } else if (QTD_CERR(token)) {
+                       status = -EPIPE;
+
+               /* In theory, more than one of the following bits can be set
+                * since they are sticky and the transaction is retried.
+                * Which to test first is rather arbitrary.
+                */
                } else if (token & QTD_STS_MMF) {
                        /* fs/ls interrupt xfer missed the complete-split */
                        status = -EPROTO;
@@ -222,21 +230,15 @@ static int qtd_copy_status (
                                ? -ENOSR  /* hc couldn't read data */
                                : -ECOMM; /* hc couldn't write data */
                } else if (token & QTD_STS_XACT) {
-                       /* timeout, bad crc, wrong PID, etc; retried */
-                       if (QTD_CERR (token))
-                               status = -EPIPE;
-                       else {
-                               ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
-                                       urb->dev->devpath,
-                                       usb_pipeendpoint (urb->pipe),
-                                       usb_pipein (urb->pipe) ? "in" : "out");
-                               status = -EPROTO;
-                       }
-               /* CERR nonzero + no errors + halt --> stall */
-               } else if (QTD_CERR (token))
-                       status = -EPIPE;
-               else    /* unknown */
+                       /* timeout, bad CRC, wrong PID, etc */
+                       ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n",
+                               urb->dev->devpath,
+                               usb_pipeendpoint(urb->pipe),
+                               usb_pipein(urb->pipe) ? "in" : "out");
+                       status = -EPROTO;
+               } else {        /* unknown */
                        status = -EPROTO;
+               }
 
                ehci_vdbg (ehci,
                        "dev%d ep%d%s qtd token %08x --> status %d\n",