diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2018-05-13 06:58:43 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2018-05-13 06:58:43 +0000 |
commit | 65a347c6597471b8584d2e0f14c7171e58976a85 (patch) | |
tree | a1ed0a71359f272822dc4b4e47a17a0f05c4ce14 /sys | |
parent | 0201b1be37ce0c796c12ae8689022fd9f3088830 (diff) |
Add bus DMA barriers to ensure the hardware does not see a TRB cycle bit
flip before the rest of the TRB is updated.
OK dlg@, pirofti@, mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/xhci.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index 6d99d051479..f4c8b4665cb 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xhci.c,v 1.85 2018/05/08 13:41:52 mpi Exp $ */ +/* $OpenBSD: xhci.c,v 1.86 2018/05/13 06:58:42 visa Exp $ */ /* * Copyright (c) 2014-2015 Martin Pieuchot @@ -1647,11 +1647,16 @@ xhci_command_submit(struct xhci_softc *sc, struct xhci_trb *trb0, int timeout) trb = xhci_ring_produce(sc, &sc->sc_cmd_ring); if (trb == NULL) return (EAGAIN); - memcpy(trb, trb0, sizeof(struct xhci_trb)); + trb->trb_paddr = trb0->trb_paddr; + trb->trb_status = trb0->trb_status; bus_dmamap_sync(sc->sc_cmd_ring.dma.tag, sc->sc_cmd_ring.dma.map, TRBOFF(&sc->sc_cmd_ring, trb), sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE); + trb->trb_flags = trb0->trb_flags; + bus_dmamap_sync(sc->sc_cmd_ring.dma.tag, sc->sc_cmd_ring.dma.map, + TRBOFF(&sc->sc_cmd_ring, trb), sizeof(struct xhci_trb), + BUS_DMASYNC_PREWRITE); if (timeout == 0) { XDWRITE4(sc, XHCI_DOORBELL(0), 0); @@ -2635,8 +2640,11 @@ xhci_device_ctrl_start(struct usbd_xfer *xfer) memcpy(&trb0->trb_paddr, &xfer->request, sizeof(trb0->trb_paddr)); trb0->trb_status = htole32(XHCI_TRB_INTR(0) | XHCI_TRB_LEN(8)); - trb0->trb_flags = htole32(flags); + bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, + TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), + BUS_DMASYNC_PREWRITE); + trb0->trb_flags = htole32(flags); bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE); @@ -2751,8 +2759,11 @@ xhci_device_generic_start(struct usbd_xfer *xfer) XHCI_TRB_INTR(0) | XHCI_TRB_LEN(len0) | xhci_xfer_tdsize(xfer, xfer->length, len0) ); - trb0->trb_flags = htole32(flags); + bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, + TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), + BUS_DMASYNC_PREWRITE); + trb0->trb_flags = htole32(flags); bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE); @@ -2883,8 +2894,11 @@ xhci_device_isoc_start(struct usbd_xfer *xfer) XHCI_TRB_INTR(0) | XHCI_TRB_LEN(len0) | xhci_xfer_tdsize(xfer, xfer->length, len0) ); - trb0->trb_flags = htole32(flags); + bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, + TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), + BUS_DMASYNC_PREWRITE); + trb0->trb_flags = htole32(flags); bus_dmamap_sync(xp->ring.dma.tag, xp->ring.dma.map, TRBOFF(&xp->ring, trb0), sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE); |