summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2018-06-27 11:38:59 +0000
committerkettenis <kettenis@openbsd.org>2018-06-27 11:38:59 +0000
commit885b1c8363bea13a093df016a1d1b9458f4661ba (patch)
tree3ee12477b461bcf09117b7b68e2ee0f2ce50d18e
parentMove rde_test_prefix() to a place where it makes more sense. No functional (diff)
downloadwireguard-openbsd-885b1c8363bea13a093df016a1d1b9458f4661ba.tar.xz
wireguard-openbsd-885b1c8363bea13a093df016a1d1b9458f4661ba.zip
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);
}