diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-06-27 11:39:00 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-06-27 11:39:00 +0000 |
commit | 0b9ce290c14de4bb5dee4d9616f0bcec50de85ce (patch) | |
tree | 8d0b855c8721e359117cd23fc407fb25511ebe79 | |
parent | f12712a8d0f5f27012552855923e8adf2a7c4074 (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.c | 45 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/vbusvar.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/vcons.c | 25 |
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); } |