Module Name: src
Committed By: bouyer
Date: Sat Jul 19 22:08:54 UTC 2014
Modified Files:
src/sys/dev/usb: motg.c
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/motg.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/motg.c
diff -u src/sys/dev/usb/motg.c:1.2 src/sys/dev/usb/motg.c:1.3
--- src/sys/dev/usb/motg.c:1.2 Thu Jul 17 19:58:18 2014
+++ src/sys/dev/usb/motg.c Sat Jul 19 22:08:54 2014
@@ -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 @@ int motgdebug = 0;
#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_read(usbd_
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 @@ motg_init(struct motg_softc *sc)
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 @@ motg_init(struct motg_softc *sc)
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 @@ motg_softintr(void *v)
if (tx_status & (0x01 << i))
motg_device_intr_tx(sc, i);
}
-
return;
}
@@ -1075,12 +1084,6 @@ motg_root_ctrl_start(usbd_xfer_handle xf
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 @@ motg_device_ctrl_transfer(usbd_xfer_hand
/* 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 @@ static usbd_status
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 @@ motg_device_ctrl_start1(struct motg_soft
/* 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 @@ motg_device_ctrl_start1(struct motg_soft
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 @@ motg_device_ctrl_intr_rx(struct motg_sof
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 @@ motg_device_ctrl_intr_rx(struct motg_sof
/* 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 @@ motg_device_ctrl_intr_rx(struct motg_sof
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 @@ motg_device_ctrl_intr_rx(struct motg_sof
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 @@ motg_device_ctrl_intr_rx(struct motg_sof
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 @@ motg_device_ctrl_intr_rx(struct motg_sof
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 @@ motg_device_ctrl_intr_tx(struct motg_sof
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 @@ motg_device_ctrl_intr_tx(struct motg_sof
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 @@ motg_device_ctrl_intr_tx(struct motg_sof
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 @@ motg_device_ctrl_intr_tx(struct motg_sof
* 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 @@ motg_device_ctrl_intr_tx(struct motg_sof
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 @@ complete:
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 @@ motg_device_data_transfer(usbd_xfer_hand
/* Insert last in queue. */
mutex_enter(&sc->sc_lock);
+ DPRINTF(("motg_device_data_transfer(%p) status %d\n",
+ xfer, xfer->status));
err = usb_insert_transfer(xfer);
+ xfer->status = USBD_NOT_STARTED;
mutex_exit(&sc->sc_lock);
if (err)
return (err);
@@ -1909,6 +1914,8 @@ motg_device_data_start(usbd_xfer_handle
struct motg_pipe *otgpipe = (struct motg_pipe *)xfer->pipe;
usbd_status err;
mutex_enter(&sc->sc_lock);
+ DPRINTF(("motg_device_data_start(%p) status %d\n",
+ xfer, xfer->status));
err = motg_device_data_start1(sc, otgpipe->hw_ep);
mutex_exit(&sc->sc_lock);
if (err != USBD_IN_PROGRESS)
@@ -1921,7 +1928,7 @@ motg_device_data_start(usbd_xfer_handle
static usbd_status
motg_device_data_start1(struct motg_softc *sc, struct motg_hw_ep *ep)
{
- usbd_xfer_handle xfer;
+ usbd_xfer_handle xfer = NULL;
struct motg_pipe *otgpipe;
usbd_status err = 0;
uint32_t val;
@@ -1940,6 +1947,9 @@ motg_device_data_start1(struct motg_soft
/* 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_BULK,
+ ("motg_device_data_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,
@@ -1953,7 +1963,7 @@ motg_device_data_start1(struct motg_soft
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
@@ -2095,6 +2105,7 @@ motg_device_intr_rx(struct motg_softc *s
int datalen, max_datalen;
char *data;
bool got_short;
+ usbd_status new_status = USBD_IN_PROGRESS;
KASSERT(mutex_owned(&sc->sc_lock));
KASSERT(ep->ep_number == epnumber);
@@ -2124,24 +2135,21 @@ motg_device_intr_rx(struct motg_softc *s
csr &= ~MUSB2_MASK_CSRL_RXNAKTO;
UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
- if (xfer)
- xfer->status = USBD_TIMEOUT; /* XXX */
+ new_status = USBD_TIMEOUT; /* XXX */
goto complete;
}
if (csr & (MUSB2_MASK_CSRL_RXSTALL | MUSB2_MASK_CSRL_RXERROR)) {
- if (xfer) {
- if (csr & MUSB2_MASK_CSRL_RXSTALL)
- xfer->status = USBD_STALLED;
- else
- xfer->status = USBD_IOERROR;
- }
+ if (csr & MUSB2_MASK_CSRL_RXSTALL)
+ new_status = USBD_STALLED;
+ else
+ new_status = USBD_IOERROR;
/* clear status */
UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
goto complete;
}
KASSERT(csr & MUSB2_MASK_CSRL_RXPKTRDY);
- if (xfer == NULL) {
+ if (xfer == NULL || xfer->status != USBD_IN_PROGRESS) {
UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
goto complete;
}
@@ -2158,7 +2166,7 @@ motg_device_intr_rx(struct motg_softc *s
UE_GET_SIZE(UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)),
ep->datalen);
if (datalen > max_datalen) {
- xfer->status = USBD_IOERROR;
+ new_status = USBD_IOERROR;
UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
goto complete;
}
@@ -2192,7 +2200,7 @@ motg_device_intr_rx(struct motg_softc *s
KASSERT(ep->phase == DATA_IN);
if (got_short || (ep->datalen == 0)) {
if (ep->need_short_xfer == 0) {
- xfer->status = USBD_NORMAL_COMPLETION;
+ new_status = USBD_NORMAL_COMPLETION;
goto complete;
}
ep->need_short_xfer = 0;
@@ -2205,8 +2213,11 @@ complete:
(xfer != NULL) ? xfer->status : 0));
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_data_start1(sc, ep);
}
@@ -2217,6 +2228,7 @@ motg_device_intr_tx(struct motg_softc *s
usbd_xfer_handle xfer = ep->xfer;
uint8_t csr;
struct motg_pipe *otgpipe;
+ usbd_status new_status = USBD_IN_PROGRESS;
KASSERT(mutex_owned(&sc->sc_lock));
KASSERT(ep->ep_number == epnumber);
@@ -2233,34 +2245,35 @@ motg_device_intr_tx(struct motg_softc *s
if (csr & (MUSB2_MASK_CSRL_TXSTALLED|MUSB2_MASK_CSRL_TXERROR)) {
/* command not accepted */
- if (xfer) {
- if (csr & MUSB2_MASK_CSRL_TXSTALLED)
- xfer->status = USBD_STALLED;
- else
- xfer->status = USBD_IOERROR;
- }
+ if (csr & MUSB2_MASK_CSRL_TXSTALLED)
+ new_status = USBD_STALLED;
+ else
+ new_status = USBD_IOERROR;
/* clear status */
UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
goto complete;
}
if (csr & MUSB2_MASK_CSRL_TXNAKTO) {
- if (xfer)
- xfer->status = USBD_TIMEOUT; /* XXX */
+ new_status = USBD_TIMEOUT; /* XXX */
+ csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
+ UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
/* flush fifo */
while (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+ csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
+ delay(1000);
csr = UREAD1(sc, MUSB2_REG_TXCSRL);
+ DPRINTFN(MD_BULK, ("TX fifo flush ep %d CSR 0x%x\n",
+ epnumber, csr));
}
- csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
- UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
goto complete;
}
if (csr & (MUSB2_MASK_CSRL_TXFIFONEMPTY|MUSB2_MASK_CSRL_TXPKTRDY)) {
/* data still not sent */
return;
}
- if (xfer == NULL)
+ if (xfer == NULL || xfer->status != USBD_IN_PROGRESS)
goto complete;
#ifdef DIAGNOSTIC
if (ep->phase != DATA_OUT)
@@ -2275,7 +2288,7 @@ motg_device_intr_tx(struct motg_softc *s
ep->need_short_xfer = 0;
/* one more data phase */
} else {
- xfer->status = USBD_NORMAL_COMPLETION;
+ new_status = USBD_NORMAL_COMPLETION;
goto complete;
}
}
@@ -2287,13 +2300,16 @@ complete:
("motg_device_intr_tx xfer %p complete, status %d\n", xfer,
(xfer != NULL) ? xfer->status : 0));
#ifdef DIAGNOSTIC
- if (xfer && ep->phase != DATA_OUT)
+ if (xfer && xfer->status == USBD_IN_PROGRESS && ep->phase != DATA_OUT)
panic("motg_device_intr_tx: bad phase %d", ep->phase);
#endif
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_data_start1(sc, ep);
}
@@ -2304,39 +2320,10 @@ motg_device_data_abort(usbd_xfer_handle
#ifdef DIAGNOSTIC
struct motg_softc *sc = xfer->pipe->device->bus->hci_private;
#endif
- struct motg_pipe *otgpipe = (struct motg_pipe *)xfer->pipe;
- uint8_t csr;
-
KASSERT(mutex_owned(&sc->sc_lock));
- DPRINTFN(MD_BULK,
- ("motg_device_data_abort:\n"));
- if (otgpipe->hw_ep->xfer == xfer) {
- otgpipe->hw_ep->xfer = NULL;
- /* select endpoint */
- UWRITE1(sc, MUSB2_REG_EPINDEX, otgpipe->hw_ep->ep_number);
- if (otgpipe->hw_ep->phase == DATA_OUT) {
- csr = UREAD1(sc, MUSB2_REG_TXCSRL);
- while (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
- csr |= MUSB2_MASK_CSRL_TXFFLUSH;
- UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
- csr = UREAD1(sc, MUSB2_REG_TXCSRL);
- }
- UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
- } else if (otgpipe->hw_ep->phase == DATA_IN) {
- csr = UREAD1(sc, MUSB2_REG_RXCSRL);
- while (csr & MUSB2_MASK_CSRL_RXPKTRDY) {
- csr |= MUSB2_MASK_CSRL_RXFFLUSH;
- UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
- csr = UREAD1(sc, MUSB2_REG_RXCSRL);
- }
- UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
- }
- otgpipe->hw_ep->phase = IDLE;
- }
-
- xfer->status = USBD_CANCELLED;
- usb_transfer_complete(xfer);
+ DPRINTFN(MD_BULK, ("motg_device_data_abort:\n"));
+ motg_device_xfer_abort(xfer);
}
/* Close a device control pipe */
@@ -2389,7 +2376,6 @@ motg_waitintr(struct motg_softc *sc, usb
DPRINTF(("motg_waitintr: timeout = %dms\n", timo));
- xfer->status = USBD_IN_PROGRESS;
for (; timo >= 0; timo--) {
mutex_exit(&sc->sc_lock);
usb_delay_ms(&sc->sc_bus, 1);
@@ -2416,3 +2402,59 @@ motg_device_clear_toggle(usbd_pipe_handl
struct motg_pipe *otgpipe = (struct motg_pipe *)pipe;
otgpipe->nexttoggle = 0;
}
+
+/* Abort a device control request. */
+static void
+motg_device_xfer_abort(usbd_xfer_handle xfer)
+{
+ int wake;
+ uint8_t csr;
+#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));
+
+ DPRINTF(("motg_device_xfer_abort:\n"));
+ if (xfer->hcflags & UXFER_ABORTING) {
+ DPRINTF(("motg_device_xfer_abort: already aborting\n"));
+ xfer->hcflags |= UXFER_ABORTWAIT;
+ while (xfer->hcflags & UXFER_ABORTING)
+ cv_wait(&xfer->hccv, &sc->sc_lock);
+ return;
+ }
+ xfer->hcflags |= UXFER_ABORTING;
+ if (otgpipe->hw_ep->xfer == xfer) {
+ KASSERT(xfer->status == USBD_IN_PROGRESS);
+ otgpipe->hw_ep->xfer = NULL;
+ if (otgpipe->hw_ep->ep_number > 0) {
+ /* select endpoint */
+ UWRITE1(sc, MUSB2_REG_EPINDEX,
+ otgpipe->hw_ep->ep_number);
+ if (otgpipe->hw_ep->phase == DATA_OUT) {
+ csr = UREAD1(sc, MUSB2_REG_TXCSRL);
+ while (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
+ csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+ UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
+ csr = UREAD1(sc, MUSB2_REG_TXCSRL);
+ }
+ UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
+ } else if (otgpipe->hw_ep->phase == DATA_IN) {
+ csr = UREAD1(sc, MUSB2_REG_RXCSRL);
+ while (csr & MUSB2_MASK_CSRL_RXPKTRDY) {
+ csr |= MUSB2_MASK_CSRL_RXFFLUSH;
+ UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
+ csr = UREAD1(sc, MUSB2_REG_RXCSRL);
+ }
+ UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
+ }
+ otgpipe->hw_ep->phase = IDLE;
+ }
+ }
+ xfer->status = USBD_CANCELLED; /* make software ignore it */
+ wake = xfer->hcflags & UXFER_ABORTWAIT;
+ xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT);
+ usb_transfer_complete(xfer);
+ if (wake)
+ cv_broadcast(&xfer->hccv);
+}