diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-12-02 09:23:24 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-12-02 09:23:24 +0000 |
commit | 9cfec9e831bb3d63991ce3bbe5fa117fdfb361c6 (patch) | |
tree | f1a92b1a422a3f001da1d8ac24180569f79cf99b /sys/dev | |
parent | e6e49107f9b2dd93bafa7ec27bf7b3e1308ca6b6 (diff) |
Do not change the status of a transfer before giving it back to the
stack.
Unbreak polling mode when the host Babbles because a reset of the ring
is necessary and xhci_waitintr() stops polling as soon as the xfer
status changed.
Problem reported by and ok krw@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/xhci.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index e4e54bc20f7..358ccf4794f 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xhci.c,v 1.65 2015/11/29 16:30:48 kettenis Exp $ */ +/* $OpenBSD: xhci.c,v 1.66 2015/12/02 09:23:23 mpi Exp $ */ /* * Copyright (c) 2014-2015 Martin Pieuchot @@ -783,15 +783,14 @@ xhci_event_xfer(struct xhci_softc *sc, uint64_t paddr, uint32_t status, /* We need to report this condition for umass(4). */ if (code == XHCI_CODE_STALL) - xfer->status = USBD_STALLED; + xp->halted = USBD_STALLED; else - xfer->status = USBD_IOERROR; + xp->halted = USBD_IOERROR; /* * Since the stack might try to start a new transfer as * soon as a pending one finishes, make sure the endpoint * is fully reset before calling usb_transfer_complete(). */ - xp->halted = 1; xp->aborted_xfer = xfer; xhci_cmd_reset_ep_async(sc, slot, dci); return; @@ -821,7 +820,7 @@ xhci_event_command(struct xhci_softc *sc, uint64_t paddr) struct xhci_pipe *xp; uint32_t flags; uint8_t dci, slot; - int trb_idx; + int trb_idx, status; trb_idx = (paddr - sc->sc_cmd_ring.dma.paddr) / sizeof(*trb); if (trb_idx < 0 || trb_idx >= sc->sc_cmd_ring.ntrb) { @@ -852,8 +851,10 @@ xhci_event_command(struct xhci_softc *sc, uint64_t paddr) if (xp == NULL) break; + status = xp->halted; xp->halted = 0; if (xp->aborted_xfer != NULL) { + xp->aborted_xfer->status = status; xhci_xfer_done(xp->aborted_xfer); wakeup(xp); } @@ -1932,8 +1933,7 @@ xhci_abort_xfer(struct usbd_xfer *xfer, usbd_status status) usb_rem_task(xfer->device, &xfer->abort_task); /* Indicate that we are aborting this transfer. */ - xfer->status = status; - xp->halted = 1; + xp->halted = status; xp->aborted_xfer = xfer; /* Stop the endpoint and wait until the hardware says so. */ |