summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2014-10-30 18:08:25 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2014-10-30 18:08:25 +0000
commit1624a3c08268e7bcaf56d4de0886ceb1430b24db (patch)
treeda1078c7928b73714fb62bbf0a8551f8cf9fab1c /sys/dev
parentd94b7bbc9d28d36a0803656a453f7f68c2b9109e (diff)
Calculate the Route String when attaching a new device. This is still
not enough to attach Super Speed devices below USB 3 hubs, but we're getting there. While here reset `acten` when re-enqueuing an interrupt transfers.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/xhci.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 2de3002a04d..e02169ed58c 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.28 2014/10/05 13:32:14 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.29 2014/10/30 18:08:24 mpi Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
@@ -79,7 +79,8 @@ void xhci_event_dequeue(struct xhci_softc *);
void xhci_event_xfer(struct xhci_softc *, uint64_t, uint32_t, uint32_t);
void xhci_event_command(struct xhci_softc *, uint64_t);
void xhci_event_port_change(struct xhci_softc *, uint64_t, uint32_t);
-int xhci_pipe_init(struct xhci_softc *, struct usbd_pipe *, uint32_t);
+int xhci_pipe_init(struct xhci_softc *, struct usbd_pipe *, uint32_t,
+ uint32_t);
int xhci_scratchpad_alloc(struct xhci_softc *, int);
void xhci_scratchpad_free(struct xhci_softc *);
int xhci_softdev_alloc(struct xhci_softc *, uint8_t);
@@ -882,7 +883,7 @@ xhci_pipe_open(struct usbd_pipe *pipe)
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
uint8_t slot = 0, xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
struct usbd_device *hub;
- uint32_t rhport = 0;
+ uint32_t route = 0, rhport = 0;
int error;
KASSERT(xp->slot == 0);
@@ -931,9 +932,19 @@ xhci_pipe_open(struct usbd_pipe *pipe)
if (xhci_softdev_alloc(sc, slot))
return (USBD_NOMEM);
- /* Get root hub port */
- for (hub = pipe->device; hub->myhub->depth; hub = hub->myhub)
- ;
+ /*
+ * Calculate the Route String. Note that this code assume
+ * that there is no hub with more than 16 ports and that
+ * they all are at a detph < USB_HUB_MAX_DEPTH.
+ */
+ for (hub = pipe->device; hub->myhub->depth; hub = hub->myhub) {
+ uint32_t port = hub->powersrc->portno;
+ uint32_t depth = hub->myhub->depth;
+
+ route |= port << (4 * (depth - 1));
+ }
+
+ /* Get Root Hub port */
rhport = hub->powersrc->portno;
break;
case UE_ISOCHRONOUS:
@@ -963,7 +974,7 @@ xhci_pipe_open(struct usbd_pipe *pipe)
else
xp->slot = ((struct xhci_pipe *)pipe->device->default_pipe)->slot;
- if (xhci_pipe_init(sc, pipe, rhport))
+ if (xhci_pipe_init(sc, pipe, rhport, route))
return (USBD_IOERROR);
return (USBD_NORMAL_COMPLETION);
@@ -1006,7 +1017,8 @@ xhci_get_txinfo(struct xhci_softc *sc, struct usbd_pipe *pipe)
}
int
-xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe, uint32_t port)
+xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe, uint32_t port,
+ uint32_t route)
{
struct xhci_pipe *xp = (struct xhci_pipe *)pipe;
struct xhci_soft_dev *sdev = &sc->sc_sdevs[xp->slot];
@@ -1058,8 +1070,8 @@ xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe, uint32_t port)
if (pipe->interval != USBD_DEFAULT_INTERVAL)
ival = min(ival, pipe->interval);
- DPRINTF(("%s: speed %d mps %d rhport %d\n", DEVNAME(sc), speed, mps,
- port));
+ DPRINTF(("%s: speed %d mps %d rhport %d route 0x%x\n", DEVNAME(sc),
+ speed, mps, port, route));
/* Setup the endpoint context */
if (xfertype != UE_ISOCHRONOUS)
@@ -1087,12 +1099,14 @@ xhci_pipe_init(struct xhci_softc *sc, struct usbd_pipe *pipe, uint32_t port)
/* Setup the slot context */
sdev->slot_ctx->info_lo = htole32(
- XHCI_SCTX_DCI(xp->dci) | XHCI_SCTX_SPEED(speed)
+ XHCI_SCTX_DCI(xp->dci) | XHCI_SCTX_SPEED(speed) |
+ XHCI_SCTX_ROUTE(route)
);
sdev->slot_ctx->info_hi = htole32(XHCI_SCTX_RHPORT(port));
sdev->slot_ctx->tt = 0;
sdev->slot_ctx->state = 0;
+ /* If we are opening the interrupt pipe of a hub, update its context. */
if (pipe->device->hub != NULL) {
int nports = pipe->device->hub->nports;
@@ -2310,8 +2324,10 @@ xhci_device_generic_done(struct usbd_xfer *xfer)
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
/* Only happens with interrupt transfers. */
- if (xfer->pipe->repeat)
- xfer->status = xhci_device_generic_start(xfer);
+ if (xfer->pipe->repeat) {
+ xfer->actlen = 0;
+ xhci_device_generic_start(xfer);
+ }
}
void