summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-06-27 11:39:00 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-06-27 11:39:00 +0000
commit0b9ce290c14de4bb5dee4d9616f0bcec50de85ce (patch)
tree8d0b855c8721e359117cd23fc407fb25511ebe79
parentf12712a8d0f5f27012552855923e8adf2a7c4074 (diff)
Rework vbus(4) interrupt handling to be similar to cbus(4). Expose functions
to ack and enable/disable interrupts and don't enable interrupts by default. Also don't ack interrupts by default. Make use of this in vcons(4) to avoid interrupt storms that may occur because of a race between the interrupt handler and the software interrupt handler. Don't enable the interrupt handler unless somebody actually has the console open. Ack the interrupt at the end of the softintr handler. Fixes console issue on SPARC T3 machines. ok claudio@
-rw-r--r--sys/arch/sparc64/dev/vbus.c45
-rw-r--r--sys/arch/sparc64/dev/vbusvar.h6
-rw-r--r--sys/arch/sparc64/dev/vcons.c25
3 files changed, 57 insertions, 19 deletions
diff --git a/sys/arch/sparc64/dev/vbus.c b/sys/arch/sparc64/dev/vbus.c
index 11894593e8e..381876fd85e 100644
--- a/sys/arch/sparc64/dev/vbus.c
+++ b/sys/arch/sparc64/dev/vbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vbus.c,v 1.10 2017/12/22 15:52:36 kettenis Exp $ */
+/* $OpenBSD: vbus.c,v 1.11 2018/06/27 11:38:59 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
*
@@ -190,6 +190,34 @@ vbus_intr_map(int node, int ino, uint64_t *sysino)
return (-1);
}
+int
+vbus_intr_setstate(bus_space_tag_t t, uint64_t sysino, uint64_t state)
+{
+ struct vbus_softc *sc = t->cookie;
+ uint64_t devhandle = sc->sc_devhandle;
+ int err;
+
+ err = sun4v_intr_setstate(devhandle, sysino, state);
+ if (err != H_EOK)
+ return (-1);
+
+ return (0);
+}
+
+int
+vbus_intr_setenabled(bus_space_tag_t t, uint64_t sysino, uint64_t enabled)
+{
+ struct vbus_softc *sc = t->cookie;
+ uint64_t devhandle = sc->sc_devhandle;
+ int err;
+
+ err = sun4v_intr_setenabled(devhandle, sysino, enabled);
+ if (err != H_EOK)
+ return (-1);
+
+ return (0);
+}
+
void *
vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
int level, int flags, int (*handler)(void *), void *arg, const char *what)
@@ -208,6 +236,10 @@ vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
if (flags & BUS_INTR_ESTABLISH_MPSAFE)
ih->ih_mpsafe = 1;
+ err = sun4v_intr_setenabled(devhandle, sysino, INTR_DISABLED);
+ if (err != H_EOK)
+ return (NULL);
+
err = sun4v_intr_setcookie(devhandle, sysino, (vaddr_t)ih);
if (err != H_EOK)
return (NULL);
@@ -224,22 +256,13 @@ vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
if (err != H_EOK)
return (NULL);
- err = sun4v_intr_setenabled(devhandle, sysino, INTR_ENABLED);
- if (err != H_EOK)
- return (NULL);
-
return (ih);
}
void
vbus_intr_ack(struct intrhand *ih)
{
- bus_space_tag_t t = ih->ih_bus;
- struct vbus_softc *sc = t->cookie;
- uint64_t devhandle = sc->sc_devhandle;
- uint64_t sysino = INTVEC(ih->ih_number);
-
- sun4v_intr_setstate(devhandle, sysino, INTR_IDLE);
+ /* Drivers explicitly ack interrupts. */
}
bus_space_tag_t
diff --git a/sys/arch/sparc64/dev/vbusvar.h b/sys/arch/sparc64/dev/vbusvar.h
index 74439df8011..ebc2cee462b 100644
--- a/sys/arch/sparc64/dev/vbusvar.h
+++ b/sys/arch/sparc64/dev/vbusvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vbusvar.h,v 1.3 2008/12/30 21:23:33 kettenis Exp $ */
+/* $OpenBSD: vbusvar.h,v 1.4 2018/06/27 11:38:59 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
*
@@ -32,6 +32,8 @@ struct vbus_attach_args {
int va_nintr;
};
-int vbus_intr_map(int, int, uint64_t *);
+int vbus_intr_map(int, int, uint64_t *);
+int vbus_intr_setstate(bus_space_tag_t, uint64_t, uint64_t);
+int vbus_intr_setenabled(bus_space_tag_t, uint64_t, uint64_t);
#endif
diff --git a/sys/arch/sparc64/dev/vcons.c b/sys/arch/sparc64/dev/vcons.c
index 3e138ed2734..df533c062e5 100644
--- a/sys/arch/sparc64/dev/vcons.c
+++ b/sys/arch/sparc64/dev/vcons.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vcons.c,v 1.16 2018/02/19 08:59:52 mpi Exp $ */
+/* $OpenBSD: vcons.c,v 1.17 2018/06/27 11:38:59 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
*
@@ -36,7 +36,10 @@
struct vcons_softc {
struct device sc_dv;
+ bus_space_tag_t sc_bustag;
+
void *sc_ih;
+ uint64_t sc_sysino;
struct tty *sc_tty;
void *sc_si;
};
@@ -78,7 +81,6 @@ vcons_attach(struct device *parent, struct device *self, void *aux)
{
struct vcons_softc *sc = (struct vcons_softc *)self;
struct vbus_attach_args *va = aux;
- uint64_t sysino;
int vcons_is_input, vcons_is_output;
int node, maj;
@@ -86,11 +88,12 @@ vcons_attach(struct device *parent, struct device *self, void *aux)
if (sc->sc_si == NULL)
panic(": can't establish soft interrupt");
- if (vbus_intr_map(va->va_node, va->va_intr[0], &sysino))
+ if (vbus_intr_map(va->va_node, va->va_intr[0], &sc->sc_sysino))
printf(": can't map interrupt\n");
- printf(": ivec 0x%llx", sysino);
+ printf(": ivec 0x%llx", sc->sc_sysino);
- sc->sc_ih = bus_intr_establish(va->va_bustag, sysino, IPL_TTY,
+ sc->sc_bustag = va->va_bustag;
+ sc->sc_ih = bus_intr_establish(sc->sc_bustag, sc->sc_sysino, IPL_TTY,
BUS_INTR_ESTABLISH_MPSAFE, vcons_intr, sc, sc->sc_dv.dv_xname);
if (sc->sc_ih == NULL) {
printf(", can't establish interrupt\n");
@@ -129,6 +132,7 @@ vcons_intr(void *arg)
if (sc->sc_tty)
softintr_schedule(sc->sc_si);
+
return (1);
}
@@ -172,6 +176,7 @@ vconsopen(dev_t dev, int flag, int mode, struct proc *p)
struct vcons_softc *sc;
struct tty *tp;
int unit = minor(dev);
+ int err;
if (unit >= vcons_cd.cd_ndevs)
return (ENXIO);
@@ -199,7 +204,11 @@ vconsopen(dev_t dev, int flag, int mode, struct proc *p)
return (EBUSY);
tp->t_state |= TS_CARR_ON;
- return ((*linesw[tp->t_line].l_open)(dev, tp, p));
+ err = (*linesw[tp->t_line].l_open)(dev, tp, p);
+ if (err == 0)
+ vbus_intr_setenabled(sc->sc_bustag, sc->sc_sysino, INTR_ENABLED);
+
+ return err;
}
int
@@ -215,6 +224,8 @@ vconsclose(dev_t dev, int flag, int mode, struct proc *p)
if (sc == NULL)
return (ENXIO);
+ vbus_intr_setenabled(sc->sc_bustag, sc->sc_sysino, INTR_DISABLED);
+
tp = sc->sc_tty;
(*linesw[tp->t_line].l_close)(tp, flag, p);
ttyclose(tp);
@@ -346,4 +357,6 @@ vcons_softintr(void *arg)
if (tp->t_state & TS_ISOPEN)
(*linesw[tp->t_line].l_rint)(c, tp);
}
+
+ vbus_intr_setstate(sc->sc_bustag, sc->sc_sysino, INTR_IDLE);
}