summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2014-11-16 18:31:07 +0000
committermpi <mpi@openbsd.org>2014-11-16 18:31:07 +0000
commit16a9d1e5c0e569144192cb9df5bba26f3f75122e (patch)
treee8945f1edaf22eb39c24ad64ff9b71f5459989f8
parentremove now unnecessary casts from hash update calls. (diff)
downloadwireguard-openbsd-16a9d1e5c0e569144192cb9df5bba26f3f75122e.tar.xz
wireguard-openbsd-16a9d1e5c0e569144192cb9df5bba26f3f75122e.zip
Two fixes to make Qemu and VMware xHCI implementations work:
1. Always unmask the slot context for the "Set Address" command. 2. Use the right spl when submitting a transfer to prevent from setting up a timer on an already completed xfer. Analyzed with and ok jsg@
-rw-r--r--sys/dev/usb/xhci.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 49af191f151..677b63aa163 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.40 2014/11/11 12:10:44 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.41 2014/11/16 18:31:07 mpi Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
@@ -1122,7 +1122,6 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_pipe *pipe)
/* XXX */
#define UHUB_IS_MTT(dev) (dev->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT)
-
/*
* If we are opening the interrupt pipe of a hub, update its
* context before putting it in the CONFIGURED state.
@@ -1130,9 +1129,6 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_pipe *pipe)
if (pipe->device->hub != NULL) {
int nports = pipe->device->hub->nports;
- /* Unmask the slot context */
- sdev->input_ctx->add_flags |= htole32(XHCI_INCTX_MASK_DCI(0));
-
sdev->slot_ctx->info_lo |= htole32(XHCI_SCTX_HUB(1));
sdev->slot_ctx->info_hi |= htole32(XHCI_SCTX_NPORTS(nports));
@@ -1162,6 +1158,9 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_pipe *pipe)
}
#undef UHUB_IS_MTT
+ /* Unmask the slot context */
+ sdev->input_ctx->add_flags |= htole32(XHCI_INCTX_MASK_DCI(0));
+
usb_syncmem(&sdev->ictx_dma, 0, sc->sc_pagesize, BUS_DMASYNC_PREWRITE);
}
@@ -2276,6 +2275,7 @@ xhci_device_ctrl_start(struct usbd_xfer *xfer)
struct xhci_trb *trb0, *trb;
uint32_t len = UGETW(xfer->request.wLength);
uint8_t toggle0, toggle;
+ int s;
KASSERT(xfer->rqflags & URQ_REQUEST);
@@ -2327,6 +2327,8 @@ xhci_device_ctrl_start(struct usbd_xfer *xfer)
usb_syncmem(&xp->ring.dma, TRBOFF(xp->ring, trb0),
3 * sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+
+ s = splusb();
XDWRITE4(sc, XHCI_DOORBELL(xp->slot), xp->dci);
xfer->status = USBD_IN_PROGRESS;
@@ -2338,6 +2340,7 @@ xhci_device_ctrl_start(struct usbd_xfer *xfer)
timeout_set(&xfer->timeout_handle, xhci_timeout, xfer);
timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
}
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -2367,6 +2370,7 @@ xhci_device_generic_start(struct usbd_xfer *xfer)
struct xhci_pipe *xp = (struct xhci_pipe *)xfer->pipe;
struct xhci_trb *trb;
uint8_t toggle;
+ int s;
KASSERT(!(xfer->rqflags & URQ_REQUEST));
@@ -2387,6 +2391,8 @@ xhci_device_generic_start(struct usbd_xfer *xfer)
usb_syncmem(&xp->ring.dma, TRBOFF(xp->ring, trb),
sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
+
+ s = splusb();
XDWRITE4(sc, XHCI_DOORBELL(xp->slot), xp->dci);
xfer->status = USBD_IN_PROGRESS;
@@ -2398,6 +2404,7 @@ xhci_device_generic_start(struct usbd_xfer *xfer)
timeout_set(&xfer->timeout_handle, xhci_timeout, xfer);
timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
}
+ splx(s);
return (USBD_IN_PROGRESS);
}