Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Disable NAK timeout on bulk transfers, I couldn'...



details:   https://anonhg.NetBSD.org/src/rev/86231c6451a8
branches:  trunk
changeset: 797505:86231c6451a8
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Jul 19 22:08:54 2014 +0000

description:
Disable NAK timeout on bulk transfers, I couldn't find a way to clear
the NAK bit not the FIFO.
Make xfer aborts more robust to races, by setting proper status and flags
in xfer.

diffstat:

 sys/dev/usb/motg.c |  264 ++++++++++++++++++++++++++++++----------------------
 1 files changed, 153 insertions(+), 111 deletions(-)

diffs (truncated from 608 to 300 lines):

diff -r 82343c57d4c8 -r 86231c6451a8 sys/dev/usb/motg.c
--- a/sys/dev/usb/motg.c        Sat Jul 19 21:22:58 2014 +0000
+++ b/sys/dev/usb/motg.c        Sat Jul 19 22:08:54 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: motg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $  */
+/*     $NetBSD: motg.c,v 1.3 2014/07/19 22:08:54 bouyer Exp $  */
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.3 2014/07/19 22:08:54 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,8 +90,8 @@
 #define POLL_TO_HIGH   10      /* 100 microframes, about 0.12s */
 
 /* bulk NAK timeouts */
-#define NAK_TO_BULK    255     /* 255 frames, about 0.25s */
-#define NAK_TO_BULK_HIGH 13    /* 8k microframes, about 1s */
+#define NAK_TO_BULK    0 /* disabled */
+#define NAK_TO_BULK_HIGH 0
 
 static void            motg_hub_change(struct motg_softc *);
 static usbd_status     motg_root_ctrl_transfer(usbd_xfer_handle);
@@ -140,7 +140,8 @@
 static void            motg_device_data_write(usbd_xfer_handle);
 
 static void            motg_waitintr(struct motg_softc *, usbd_xfer_handle);
-static void            motg_device_clear_toggle(usbd_pipe_handle pipe);
+static void            motg_device_clear_toggle(usbd_pipe_handle);
+static void            motg_device_xfer_abort(usbd_xfer_handle);
 
 #define MOTG_INTR_ENDPT 1
 #define UBARR(sc) bus_space_barrier((sc)->sc_iot, (sc)->sc_ioh, 0, (sc)->sc_size, \
@@ -352,13 +353,17 @@
                        if (fiforx_size && (i <= nrx)) {
                                fiforx_size = fifo_size;
                                if (fifo_size > 7) {
+#if 0
                                        UWRITE1(sc, MUSB2_REG_RXFIFOSZ,  
                                            MUSB2_VAL_FIFOSZ(fifo_size) |
                                            MUSB2_MASK_FIFODB);
+#else
+                                       UWRITE1(sc, MUSB2_REG_RXFIFOSZ,  
+                                           MUSB2_VAL_FIFOSZ(fifo_size));
+#endif
                                } else {
                                        UWRITE1(sc, MUSB2_REG_RXFIFOSZ,  
-                                           MUSB2_VAL_FIFOSZ(fifo_size) |
-                                           MUSB2_MASK_FIFODB);
+                                           MUSB2_VAL_FIFOSZ(fifo_size));
                                }
                                UWRITE2(sc, MUSB2_REG_RXFIFOADD,  
                                    offset >> 3);
@@ -367,9 +372,14 @@
                        if (fifotx_size && (i <= ntx)) {
                                fifotx_size = fifo_size;
                                if (fifo_size > 7) {
+#if 0
                                        UWRITE1(sc, MUSB2_REG_TXFIFOSZ,  
                                            MUSB2_VAL_FIFOSZ(fifo_size) |     
                                            MUSB2_MASK_FIFODB);
+#else
+                                       UWRITE1(sc, MUSB2_REG_TXFIFOSZ,  
+                                           MUSB2_VAL_FIFOSZ(fifo_size));      
+#endif
                                } else {
                                        UWRITE1(sc, MUSB2_REG_TXFIFOSZ,  
                                            MUSB2_VAL_FIFOSZ(fifo_size));      
@@ -639,7 +649,6 @@
                if (tx_status & (0x01 << i))
                        motg_device_intr_tx(sc, i);
        }
-
        return;
 }
 
@@ -1075,12 +1084,6 @@
                        change |= UPS_C_PORT_ENABLED;
                        sc->sc_port_enabled_changed = 0;
                }
-#if 0 /*XXX*/
-               if (x & MOTG_PORTSC_OCI)
-                       status |= UPS_OVERCURRENT_INDICATOR;
-               if (x & MOTG_PORTSC_OCIC)
-                       change |= UPS_C_OVERCURRENT_INDICATOR;
-#endif
                if (sc->sc_port_suspended)
                        status |= UPS_SUSPEND;
                if (sc->sc_high_speed)
@@ -1448,6 +1451,7 @@
        /* Insert last in queue. */
        mutex_enter(&sc->sc_lock);
        err = usb_insert_transfer(xfer);
+       xfer->status = USBD_NOT_STARTED;
        mutex_exit(&sc->sc_lock);
        if (err)
                return (err);
@@ -1478,7 +1482,7 @@
 motg_device_ctrl_start1(struct motg_softc *sc)
 {
        struct motg_hw_ep *ep = &sc->sc_in_ep[0];
-       usbd_xfer_handle xfer;
+       usbd_xfer_handle xfer = NULL;
        struct motg_pipe *otgpipe;
        usbd_status err = 0;
 
@@ -1496,6 +1500,10 @@
        /* locate the first pipe with work to do */
        SIMPLEQ_FOREACH(otgpipe, &ep->ep_pipes, ep_pipe_list) {
                xfer = SIMPLEQ_FIRST(&otgpipe->pipe.queue);
+               DPRINTFN(MD_CTRL,
+                   ("motg_device_ctrl_start1 pipe %p xfer %p status %d\n",
+                   otgpipe, xfer, (xfer != NULL) ? xfer->status : 0));
+                   
                if (xfer != NULL) {
                        /* move this pipe to the end of the list */
                        SIMPLEQ_REMOVE(&ep->ep_pipes, otgpipe,
@@ -1509,7 +1517,7 @@
                err = USBD_NOT_STARTED;
                goto end;
        }
-       KASSERT(xfer != NULL);
+       xfer->status = USBD_IN_PROGRESS;
        KASSERT(otgpipe == (struct motg_pipe *)xfer->pipe);
        KASSERT(otgpipe->hw_ep == ep);
 #ifdef DIAGNOSTIC
@@ -1580,6 +1588,7 @@
        int datalen, max_datalen;
        char *data;
        bool got_short;
+       usbd_status new_status = USBD_IN_PROGRESS;
 
        KASSERT(mutex_owned(&sc->sc_lock));
 
@@ -1594,8 +1603,8 @@
        /* read out FIFO status */
        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
        DPRINTFN(MD_CTRL, 
-           ("motg_device_ctrl_intr_rx phase %d csr 0x%x\n", 
-           ep->phase, csr));
+           ("motg_device_ctrl_intr_rx phase %d csr 0x%x xfer %p status %d\n", 
+           ep->phase, csr, xfer, (xfer != NULL) ? xfer->status : 0));
 
        if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
                csr &= ~MUSB2_MASK_CSR0L_REQPKT;
@@ -1603,17 +1612,14 @@
 
                csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
                UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
-               if (xfer)
-                       xfer->status = USBD_TIMEOUT; /* XXX */
+               new_status = USBD_TIMEOUT; /* XXX */
                goto complete;
        }
        if (csr & (MUSB2_MASK_CSR0L_RXSTALL | MUSB2_MASK_CSR0L_ERROR)) {
-               if (xfer) {
-                       if (csr & MUSB2_MASK_CSR0L_RXSTALL)
-                               xfer->status = USBD_STALLED;
-                       else
-                               xfer->status = USBD_IOERROR;
-               }
+               if (csr & MUSB2_MASK_CSR0L_RXSTALL)
+                       new_status = USBD_STALLED;
+               else
+                       new_status = USBD_IOERROR;
                /* clear status */
                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                goto complete;
@@ -1621,11 +1627,11 @@
        if ((csr & MUSB2_MASK_CSR0L_RXPKTRDY) == 0)
                return; /* no data yet */
 
-       if (xfer == NULL)
+       if (xfer == NULL || xfer->status != USBD_IN_PROGRESS)
                goto complete;
 
        if (ep->phase == STATUS_IN) {
-               xfer->status = USBD_NORMAL_COMPLETION;
+               new_status = USBD_NORMAL_COMPLETION;
                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                goto complete;
        }
@@ -1637,7 +1643,7 @@
        max_datalen = min(UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize),
            ep->datalen);
        if (datalen > max_datalen) {
-               xfer->status = USBD_IOERROR;
+               new_status = USBD_IOERROR;
                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                goto complete;
        }
@@ -1687,8 +1693,11 @@
 complete:
        ep->phase = IDLE;
        ep->xfer = NULL;
-       if (xfer)
+       if (xfer && xfer->status == USBD_IN_PROGRESS) {
+               KASSERT(new_status != USBD_IN_PROGRESS);
+               xfer->status = new_status;
                usb_transfer_complete(xfer);
+       }
        motg_device_ctrl_start1(sc);
 }
 
@@ -1700,6 +1709,7 @@
        uint8_t csr;
        int datalen;
        char *data;
+       usbd_status new_status = USBD_IN_PROGRESS;
 
        KASSERT(mutex_owned(&sc->sc_lock));
        if (ep->phase == DATA_IN || ep->phase == STATUS_IN) {
@@ -1717,20 +1727,18 @@
 
        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
        DPRINTFN(MD_CTRL, 
-           ("motg_device_ctrl_intr_tx phase %d csr 0x%x\n", 
-           ep->phase, csr));
+           ("motg_device_ctrl_intr_tx phase %d csr 0x%x xfer %p status %d\n", 
+           ep->phase, csr, xfer, (xfer != NULL) ? xfer->status : 0));
 
        if (csr & MUSB2_MASK_CSR0L_RXSTALL) {
                /* command not accepted */
-               if (xfer)
-                       xfer->status = USBD_STALLED;
+               new_status = USBD_STALLED;
                /* clear status */
                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                goto complete;
        }
        if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
-               if (xfer)
-                       xfer->status = USBD_TIMEOUT; /* XXX */
+               new_status = USBD_TIMEOUT; /* XXX */
                /* flush fifo */
                while (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
                        UWRITE1(sc, MUSB2_REG_TXCSRH,
@@ -1743,8 +1751,7 @@
                goto complete;
        }
        if (csr & MUSB2_MASK_CSR0L_ERROR) {
-               if (xfer)
-                       xfer->status = USBD_IOERROR;
+               new_status = USBD_IOERROR;
                /* clear status */
                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                goto complete;
@@ -1761,8 +1768,9 @@
                 * declare transfer complete
                 */
                DPRINTFN(MD_CTRL, 
-                   ("motg_device_ctrl_intr_tx %p complete\n", xfer));
-               xfer->status = USBD_NORMAL_COMPLETION;
+                   ("motg_device_ctrl_intr_tx %p status %d complete\n",
+                       xfer, xfer->status));
+               new_status = USBD_NORMAL_COMPLETION;
                goto complete;
        }
        if (ep->datalen == 0) {
@@ -1826,8 +1834,11 @@
 complete:
        ep->phase = IDLE;
        ep->xfer = NULL;
-       if (xfer)
+       if (xfer && xfer->status == USBD_IN_PROGRESS) {
+               KASSERT(new_status != USBD_IN_PROGRESS);
+               xfer->status = new_status;
                usb_transfer_complete(xfer);
+       }
        motg_device_ctrl_start1(sc);
 }
 
@@ -1835,17 +1846,8 @@
 void
 motg_device_ctrl_abort(usbd_xfer_handle xfer)
 {
-#ifdef DIAGNOSTIC
-       struct motg_softc *sc = xfer->pipe->device->bus->hci_private;
-#endif
-       struct motg_pipe *otgpipe = (struct motg_pipe *)xfer->pipe;
-       KASSERT(mutex_owned(&sc->sc_lock));
-
        DPRINTFN(MD_CTRL, ("motg_device_ctrl_abort:\n"));
-       if (otgpipe->hw_ep->xfer == xfer)
-               otgpipe->hw_ep->xfer = NULL;
-       xfer->status = USBD_CANCELLED;
-       usb_transfer_complete(xfer);
+       motg_device_xfer_abort(xfer);
 }
 
 /* Close a device control pipe */
@@ -1890,7 +1892,10 @@
 
        /* Insert last in queue. */



Home | Main Index | Thread Index | Old Index