summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2010-12-06 06:09:09 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2010-12-06 06:09:09 +0000
commita1943ecfb9901f009cb1b08eaff4331baf5a6861 (patch)
tree15cc445d9148996872b04adc3ef749bacaff2442
parent02eb10086e614563bdbef1d69386c6bc91518f18 (diff)
* if we got an undercoverable error, set the dying flag
* check the dying flag in timeout and interrupt handlers fixes crash when disconnecting cardbus usb adapters
-rw-r--r--sys/dev/usb/ehci.c24
-rw-r--r--sys/dev/usb/ohci.c8
-rw-r--r--sys/dev/usb/uhci.c8
3 files changed, 30 insertions, 10 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 8ddb3e3de0c..361a0dbcb82 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.113 2010/10/23 15:42:09 jakemsr Exp $ */
+/* $OpenBSD: ehci.c,v 1.114 2010/12/06 06:09:08 jakemsr Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -585,6 +585,13 @@ ehci_intr1(ehci_softc_t *sc)
EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */
sc->sc_bus.intr_context++;
sc->sc_bus.no_intrs++;
+ if (eintrs & EHCI_STS_HSE) {
+ printf("%s: unrecoverable error, controller halted\n",
+ sc->sc_bus.bdev.dv_xname);
+ sc->sc_dying = 1;
+ sc->sc_bus.intr_context--;
+ return (1);
+ }
if (eintrs & EHCI_STS_IAA) {
DPRINTF(("ehci_intr1: door bell\n"));
wakeup(&sc->sc_async_head);
@@ -597,11 +604,6 @@ ehci_intr1(ehci_softc_t *sc)
usb_schedsoftintr(&sc->sc_bus);
eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT);
}
- if (eintrs & EHCI_STS_HSE) {
- printf("%s: unrecoverable error, controller halted\n",
- sc->sc_bus.bdev.dv_xname);
- /* XXX what else */
- }
if (eintrs & EHCI_STS_PCD) {
ehci_pcd(sc, sc->sc_intrxfer);
eintrs &= ~EHCI_STS_PCD;
@@ -655,6 +657,9 @@ ehci_softintr(void *v)
DPRINTFN(10,("%s: ehci_softintr (%d)\n", sc->sc_bus.bdev.dv_xname,
sc->sc_bus.intr_context));
+ if (sc->sc_dying)
+ return;
+
sc->sc_bus.intr_context++;
/*
@@ -3091,11 +3096,14 @@ void
ehci_intrlist_timeout(void *arg)
{
ehci_softc_t *sc = arg;
- int s = splusb();
+ int s;
+ if (sc->sc_dying)
+ return;
+
+ s = splusb();
DPRINTFN(1, ("ehci_intrlist_timeout\n"));
usb_schedsoftintr(&sc->sc_bus);
-
splx(s);
}
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index b92589a2940..199cd1c0a32 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.101 2010/10/28 16:07:33 deraadt Exp $ */
+/* $OpenBSD: ohci.c,v 1.102 2010/12/06 06:09:08 jakemsr Exp $ */
/* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
@@ -1214,6 +1214,9 @@ ohci_rhsc_enable(void *v_sc)
ohci_softc_t *sc = v_sc;
int s;
+ if (sc->sc_dying)
+ return;
+
s = splhardusb();
ohci_rhsc(sc, sc->sc_intrxfer);
DPRINTFN(2, ("%s: rhsc interrupt enabled\n",
@@ -1294,6 +1297,9 @@ ohci_softintr(void *v)
DPRINTFN(10,("ohci_softintr: enter\n"));
+ if (sc->sc_dying)
+ return;
+
sc->sc_bus.intr_context++;
s = splhardusb();
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index ff2ef3e00c1..cfb274ea752 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci.c,v 1.87 2010/12/06 05:48:56 jakemsr Exp $ */
+/* $OpenBSD: uhci.c,v 1.88 2010/12/06 06:09:08 jakemsr 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 $ */
@@ -929,6 +929,9 @@ uhci_poll_hub(void *addr)
DPRINTFN(20, ("uhci_poll_hub\n"));
+ if (sc->sc_dying)
+ return;
+
timeout_del(&sc->sc_poll_handle);
timeout_set(&sc->sc_poll_handle, uhci_poll_hub, xfer);
timeout_add(&sc->sc_poll_handle, sc->sc_ival);
@@ -1221,6 +1224,9 @@ uhci_softintr(void *v)
DPRINTFN(10,("%s: uhci_softintr (%d)\n", sc->sc_bus.bdev.dv_xname,
sc->sc_bus.intr_context));
+ if (sc->sc_dying)
+ return;
+
sc->sc_bus.intr_context++;
/*