summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2014-05-18 17:10:28 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2014-05-18 17:10:28 +0000
commit1e415c18717f1b7716f404d580bb7d2fe6abfd76 (patch)
treec7ca3a56c85b552ff6816cb618bf257629018b95 /sys
parent58a1099b1ac7a621a8eedf102ef167e77d76a6d8 (diff)
Do not pass an xfer pointer to the timeout routine checking for root hub
status changes because it might be freed when detaching the root uhub(4). Also do not reschedule a timeout if the pipe is being aborted. Finally do not add more code to retrieve the 'bInterval' value of the root hub endpoint descriptor since this value is hardcoded in the uhci(4) driver.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/uhci.c69
-rw-r--r--sys/dev/usb/uhcivar.h7
2 files changed, 29 insertions, 47 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index e3bd38aadea..04d6f0f2dd6 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci.c,v 1.118 2014/05/16 19:00:18 mpi Exp $ */
+/* $OpenBSD: uhci.c,v 1.119 2014/05/18 17:10:27 mpi Exp $ */
/* $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -481,7 +481,7 @@ uhci_init(struct uhci_softc *sc)
LIST_INIT(&sc->sc_intrhead);
- timeout_set(&sc->sc_poll_handle, NULL, NULL);
+ timeout_set(&sc->sc_root_intr, uhci_poll_hub, sc);
/* Set up the bus struct. */
sc->sc_bus.methods = &uhci_bus_methods;
@@ -511,8 +511,6 @@ uhci_activate(struct device *self, int act)
uhci_dumpregs(sc);
#endif
rv = config_activate_children(self, act);
- if (sc->sc_intr_xfer != NULL)
- timeout_del(&sc->sc_poll_handle);
sc->sc_bus.use_polling++;
uhci_run(sc, 0); /* stop the controller */
@@ -557,12 +555,6 @@ uhci_activate(struct device *self, int act)
uhci_run(sc, 1); /* and start traffic again */
usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
sc->sc_bus.use_polling--;
- if (sc->sc_intr_xfer != NULL) {
- timeout_del(&sc->sc_poll_handle);
- timeout_set(&sc->sc_poll_handle, uhci_poll_hub,
- sc->sc_intr_xfer);
- timeout_add_msec(&sc->sc_poll_handle, sc->sc_ival);
- }
#ifdef UHCI_DEBUG
if (uhcidebug > 2)
uhci_dumpregs(sc);
@@ -587,10 +579,7 @@ uhci_detach(struct device *self, int flags)
if (rv != 0)
return (rv);
- if (sc->sc_intr_xfer != NULL) {
- timeout_del(&sc->sc_poll_handle);
- sc->sc_intr_xfer = NULL;
- }
+ KASSERT(sc->sc_intrxfer == NULL);
/* XXX free other data structures XXX */
@@ -820,19 +809,17 @@ void exdump(void) { uhci_dump_xfers(thesc); }
void
uhci_poll_hub(void *addr)
{
- struct usbd_xfer *xfer = addr;
- struct uhci_softc *sc = (struct uhci_softc *)xfer->device->bus;
+ struct uhci_softc *sc = addr;
+ struct usbd_xfer *xfer;
int s;
u_char *p;
- DPRINTFN(20, ("uhci_poll_hub\n"));
-
if (sc->sc_bus.dying)
return;
- timeout_del(&sc->sc_poll_handle);
- timeout_set(&sc->sc_poll_handle, uhci_poll_hub, xfer);
- timeout_add_msec(&sc->sc_poll_handle, sc->sc_ival);
+ xfer = sc->sc_intrxfer;
+ if (xfer == NULL)
+ return;
p = KERNADDR(&xfer->dmabuf, 0);
p[0] = 0;
@@ -840,12 +827,15 @@ uhci_poll_hub(void *addr)
p[0] |= 1<<1;
if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<2;
- if (p[0] == 0)
+ if (p[0] == 0) {
/* No change, try again in a while */
+ timeout_add_msec(&sc->sc_root_intr, 255);
return;
+ }
- xfer->actlen = 1;
+ xfer->actlen = xfer->length;
xfer->status = USBD_NORMAL_COMPLETION;
+
s = splusb();
xfer->device->bus->intr_context++;
usb_transfer_complete(xfer);
@@ -854,11 +844,6 @@ uhci_poll_hub(void *addr)
}
void
-uhci_root_intr_done(struct usbd_xfer *xfer)
-{
-}
-
-void
uhci_root_ctrl_done(struct usbd_xfer *xfer)
{
}
@@ -3297,8 +3282,8 @@ uhci_root_intr_abort(struct usbd_xfer *xfer)
struct uhci_softc *sc = (struct uhci_softc *)xfer->device->bus;
int s;
- timeout_del(&sc->sc_poll_handle);
- sc->sc_intr_xfer = NULL;
+ timeout_del(&sc->sc_root_intr);
+ sc->sc_intrxfer = NULL;
xfer->status = USBD_CANCELLED;
s = splusb();
@@ -3328,27 +3313,25 @@ uhci_root_intr_start(struct usbd_xfer *xfer)
{
struct uhci_softc *sc = (struct uhci_softc *)xfer->device->bus;
- DPRINTFN(3, ("uhci_root_intr_start: xfer=%p len=%u flags=%d\n",
- xfer, xfer->length, xfer->flags));
-
if (sc->sc_bus.dying)
return (USBD_IOERROR);
- sc->sc_ival = xfer->pipe->endpoint->edesc->bInterval;
- timeout_del(&sc->sc_poll_handle);
- timeout_set(&sc->sc_poll_handle, uhci_poll_hub, xfer);
- timeout_add_msec(&sc->sc_poll_handle, sc->sc_ival);
- sc->sc_intr_xfer = xfer;
+ sc->sc_intrxfer = xfer;
+ timeout_add_msec(&sc->sc_root_intr, 255);
+
return (USBD_IN_PROGRESS);
}
-/* Close the root interrupt pipe. */
void
uhci_root_intr_close(struct usbd_pipe *pipe)
{
- struct uhci_softc *sc = (struct uhci_softc *)pipe->device->bus;
+}
+
+void
+uhci_root_intr_done(struct usbd_xfer *xfer)
+{
+ struct uhci_softc *sc = (struct uhci_softc *)xfer->device->bus;
- timeout_del(&sc->sc_poll_handle);
- sc->sc_intr_xfer = NULL;
- DPRINTF(("uhci_root_intr_close\n"));
+ if (xfer->pipe->repeat)
+ timeout_add_msec(&sc->sc_root_intr, 255);
}
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index 8e4c45c11f0..77801bba836 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhcivar.h,v 1.32 2014/05/16 18:17:03 mpi Exp $ */
+/* $OpenBSD: uhcivar.h,v 1.33 2014/05/18 17:10:27 mpi Exp $ */
/* $NetBSD: uhcivar.h,v 1.36 2002/12/31 00:39:11 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.14 1999/11/17 22:33:42 n_hibma Exp $ */
@@ -151,9 +151,8 @@ struct uhci_softc {
LIST_HEAD(, uhci_xfer) sc_intrhead;
/* Info for the root hub interrupt "pipe". */
- int sc_ival; /* time between root hub intrs */
- struct usbd_xfer *sc_intr_xfer; /* root hub interrupt transfer */
- struct timeout sc_poll_handle;
+ struct usbd_xfer *sc_intrxfer;
+ struct timeout sc_root_intr;
char sc_vendor[32]; /* vendor string for root hub */
int sc_id_vendor; /* vendor ID for root hub */