diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-11-02 14:55:42 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-11-02 14:55:42 +0000 |
commit | 5b84d5478b4813f32f8eb420a1b25c7bb61908bd (patch) | |
tree | f32a4bf2bbf041e7b4302644536cd983cfb6e433 /sys/dev/usb | |
parent | 80611f284849af2117598935c6576d43f8f6b16a (diff) |
Delay root hub interrupt processing to the soft-interrupt path in order
to mark ehci_intr() as IPL_MPSAFE.
Earlier version tested by ratchov@, ok visa@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/ehci.c | 15 | ||||
-rw-r--r-- | sys/dev/usb/ehcivar.h | 3 |
2 files changed, 11 insertions, 7 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 32f4fe4ccf7..71cb15f6542 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci.c,v 1.187 2015/06/26 11:17:34 mpi Exp $ */ +/* $OpenBSD: ehci.c,v 1.188 2015/11/02 14:55:41 mpi Exp $ */ /* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */ /* @@ -540,13 +540,12 @@ ehci_intr1(struct ehci_softc *sc) return (0); 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_bus.dying = 1; - sc->sc_bus.intr_context--; return (1); } if (eintrs & EHCI_STS_IAA) { @@ -558,12 +557,11 @@ ehci_intr1(struct ehci_softc *sc) eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT); } if (eintrs & EHCI_STS_PCD) { - ehci_pcd(sc, sc->sc_intrxfer); + atomic_setbits_int(&sc->sc_flags, EHCIF_PCB_INTR); + usb_schedsoftintr(&sc->sc_bus); eintrs &= ~EHCI_STS_PCD; } - sc->sc_bus.intr_context--; - if (eintrs != 0) { /* Block unprocessed interrupts. */ sc->sc_eintrs &= ~eintrs; @@ -645,6 +643,11 @@ ehci_softintr(void *v) sc->sc_bus.intr_context++; + if (sc->sc_flags & EHCIF_PCB_INTR) { + atomic_clearbits_int(&sc->sc_flags, EHCIF_PCB_INTR); + ehci_pcd(sc, sc->sc_intrxfer); + } + /* * The only explanation I can think of for why EHCI is as brain dead * as UHCI interrupt-wise is that Intel was involved in both. diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index 4cac006096b..86b36405ecc 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ehcivar.h,v 1.35 2015/04/10 13:56:42 mpi Exp $ */ +/* $OpenBSD: ehcivar.h,v 1.36 2015/11/02 14:55:41 mpi Exp $ */ /* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ /* @@ -129,6 +129,7 @@ struct ehci_softc { u_int sc_offs; /* offset to operational regs */ int sc_flags; /* misc flags */ #define EHCIF_DROPPED_INTR_WORKAROUND 0x01 +#define EHCIF_PCB_INTR 0x02 char sc_vendor[16]; /* vendor string for root hub */ int sc_id_vendor; /* vendor ID for root hub */ |