summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-11-02 14:55:42 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-11-02 14:55:42 +0000
commit5b84d5478b4813f32f8eb420a1b25c7bb61908bd (patch)
treef32a4bf2bbf041e7b4302644536cd983cfb6e433 /sys/dev/usb
parent80611f284849af2117598935c6576d43f8f6b16a (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.c15
-rw-r--r--sys/dev/usb/ehcivar.h3
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 */