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); +}