diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-12-06 06:09:09 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-12-06 06:09:09 +0000 |
commit | a1943ecfb9901f009cb1b08eaff4331baf5a6861 (patch) | |
tree | 15cc445d9148996872b04adc3ef749bacaff2442 /sys/dev/usb | |
parent | 02eb10086e614563bdbef1d69386c6bc91518f18 (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
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/ehci.c | 24 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 8 | ||||
-rw-r--r-- | sys/dev/usb/uhci.c | 8 |
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++; /* |