Pull enabling/disabling wakeup interrupt handling out of the aplintc(4)
authorkettenis <kettenis@openbsd.org>
Wed, 21 Dec 2022 22:30:42 +0000 (22:30 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 21 Dec 2022 22:30:42 +0000 (22:30 +0000)
DVACT_SUSPEND/DVACT_RESUME handling and push it into the MD code that
handles "suspend-to-idle".  This way a failure in DVACT_SUSPEND handling
will not result in hosed interrupts on the primary interrupt controller
if we abort the suspend operation.

requested by deraadt@
ok patrick@

sys/arch/arm64/arm64/cpu.c
sys/arch/arm64/arm64/intr.c
sys/arch/arm64/dev/agintc.c
sys/arch/arm64/dev/ampintc.c
sys/arch/arm64/dev/aplintc.c
sys/arch/arm64/dev/aplmbox.c
sys/arch/arm64/dev/bcm2836_intr.c
sys/arch/arm64/include/intr.h

index 6dbdb8e..0aa5623 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.76 2022/12/10 10:13:58 patrick Exp $        */
+/*     $OpenBSD: cpu.c,v 1.77 2022/12/21 22:30:42 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -1168,16 +1168,14 @@ cpu_suspend_primary(void)
                 * by clearing the flag.
                 */
                cpu_suspended = 1;
-               arm_intr_func.setipl(IPL_NONE);
-               intr_enable();
+               intr_enable_wakeup();
 
                while (cpu_suspended) {
                        __asm volatile("wfi");
                        count++;
                }
 
-               intr_disable();
-               arm_intr_func.setipl(IPL_HIGH);
+               intr_disable_wakeup();
 
                /* Unmask clock interrupts. */
                WRITE_SPECIALREG(cntv_ctl_el0,
index 9a95f91..34dd9c5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.26 2022/11/09 19:18:11 kettenis Exp $ */
+/* $OpenBSD: intr.c,v 1.27 2022/12/21 22:30:42 kettenis Exp $ */
 /*
  * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
  *
@@ -701,12 +701,15 @@ arm_do_pending_intr(int pcpl)
 void
 arm_set_intr_handler(int (*raise)(int), int (*lower)(int),
     void (*x)(int), void (*setipl)(int), void (*irq_dispatch)(void *),
-    void (*fiq_dispatch)(void *))
+    void (*fiq_dispatch)(void *), void (*enable_wakeup)(void),
+    void (*disable_wakeup)(void))
 {
        arm_intr_func.raise = raise;
        arm_intr_func.lower = lower;
        arm_intr_func.x = x;
        arm_intr_func.setipl = setipl;
+       arm_intr_func.enable_wakeup = enable_wakeup;
+       arm_intr_func.disable_wakeup = disable_wakeup;
 
        if (irq_dispatch)
                arm_irq_dispatch = irq_dispatch;
@@ -871,13 +874,31 @@ intr_barrier(void *cookie)
 }
 
 void
-intr_enable_wakeup(void *cookie)
+intr_set_wakeup(void *cookie)
 {
        struct machine_intr_handle *ih = cookie;
        struct interrupt_controller *ic = ih->ih_ic;
 
-       if (ic->ic_enable_wakeup)
-               ic->ic_enable_wakeup(ih->ih_ih);
+       if (ic->ic_set_wakeup)
+               ic->ic_set_wakeup(ih->ih_ih);
+}
+
+void
+intr_enable_wakeup(void)
+{
+       if (arm_intr_func.enable_wakeup)
+               arm_intr_func.enable_wakeup();
+       arm_intr_func.setipl(IPL_NONE);
+       intr_enable();
+}
+
+void
+intr_disable_wakeup(void)
+{
+       intr_disable();
+       arm_intr_func.setipl(IPL_HIGH);
+       if (arm_intr_func.disable_wakeup)
+               arm_intr_func.disable_wakeup();
 }
 
 /*
index dc5c899..a39bada 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: agintc.c,v 1.44 2022/10/13 18:34:56 kettenis Exp $ */
+/* $OpenBSD: agintc.c,v 1.45 2022/12/21 22:30:42 kettenis Exp $ */
 /*
  * Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn <drahn@dalerahn.com>
  * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
@@ -542,7 +542,7 @@ agintc_attach(struct device *parent, struct device *self, void *aux)
 
        /* insert self as interrupt handler */
        arm_set_intr_handler(agintc_splraise, agintc_spllower, agintc_splx,
-           agintc_setipl, agintc_irq_handler, NULL);
+           agintc_setipl, agintc_irq_handler, NULL, NULL, NULL);
 
        /* enable interrupts */
        ctrl = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, GICD_CTLR);
index df59eaf..f7926fe 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ampintc.c,v 1.29 2022/07/16 12:07:55 kettenis Exp $ */
+/* $OpenBSD: ampintc.c,v 1.30 2022/12/21 22:30:42 kettenis Exp $ */
 /*
  * Copyright (c) 2007,2009,2011 Dale Rahn <drahn@openbsd.org>
  *
@@ -290,7 +290,7 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
 
        /* insert self as interrupt handler */
        arm_set_intr_handler(ampintc_splraise, ampintc_spllower, ampintc_splx,
-           ampintc_setipl, ampintc_irq_handler, NULL);
+           ampintc_setipl, ampintc_irq_handler, NULL, NULL, NULL);
 
 #ifdef MULTIPROCESSOR
        /* setup IPI interrupts */
index 43f8254..2824f6c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplintc.c,v 1.17 2022/11/09 19:18:11 kettenis Exp $   */
+/*     $OpenBSD: aplintc.c,v 1.18 2022/12/21 22:30:42 kettenis Exp $   */
 /*
  * Copyright (c) 2021 Mark Kettenis
  *
@@ -163,11 +163,9 @@ struct aplintc_softc *aplintc_sc;
 
 int    aplintc_match(struct device *, void *, void *);
 void   aplintc_attach(struct device *, struct device *, void *);
-int    aplintc_activate(struct device *, int act);
 
-const struct cfattach  aplintc_ca = {
-       sizeof (struct aplintc_softc), aplintc_match, aplintc_attach,
-       NULL, aplintc_activate
+const struct cfattach aplintc_ca = {
+       sizeof (struct aplintc_softc), aplintc_match, aplintc_attach
 };
 
 struct cfdriver aplintc_cd = {
@@ -182,11 +180,13 @@ int       aplintc_splraise(int);
 int    aplintc_spllower(int);
 void   aplintc_splx(int);
 void   aplintc_setipl(int);
+void   aplintc_enable_wakeup(void);
+void   aplintc_disable_wakeup(void);
 
 void   *aplintc_intr_establish(void *, int *, int, struct cpu_info *,
            int (*)(void *), void *, char *);
 void   aplintc_intr_disestablish(void *);
-void   aplintc_intr_enable_wakeup(void *);
+void   aplintc_intr_set_wakeup(void *);
 
 void   aplintc_send_ipi(struct cpu_info *, int);
 void   aplintc_handle_ipi(struct aplintc_softc *);
@@ -272,7 +272,8 @@ aplintc_attach(struct device *parent, struct device *self, void *aux)
 
        evcount_attach(&sc->sc_ipi_count, "ipi", NULL);
        arm_set_intr_handler(aplintc_splraise, aplintc_spllower, aplintc_splx,
-           aplintc_setipl, aplintc_irq_handler, aplintc_fiq_handler);
+           aplintc_setipl, aplintc_irq_handler, aplintc_fiq_handler,
+           aplintc_enable_wakeup, aplintc_disable_wakeup);
 
        sc->sc_ic.ic_node = faa->fa_node;
        sc->sc_ic.ic_cookie = self;
@@ -280,7 +281,7 @@ aplintc_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_ic.ic_disestablish = aplintc_intr_disestablish;
        sc->sc_ic.ic_cpu_enable = aplintc_cpuinit;
        sc->sc_ic.ic_barrier = aplintc_intr_barrier;
-       sc->sc_ic.ic_enable_wakeup = aplintc_intr_enable_wakeup;
+       sc->sc_ic.ic_set_wakeup = aplintc_intr_set_wakeup;
        arm_intr_register_fdt(&sc->sc_ic);
 
 #ifdef MULTIPROCESSOR
@@ -291,39 +292,6 @@ aplintc_attach(struct device *parent, struct device *self, void *aux)
                HSET4(sc, AIC2_CONFIG, AIC2_CONFIG_ENABLE);
 }
 
-int
-aplintc_activate(struct device *self, int act)
-{
-       struct aplintc_softc *sc = (struct aplintc_softc *)self;
-       struct intrhand *ih;
-       int die, irq;
-
-       switch (act) {
-       case DVACT_SUSPEND:
-               for (die = 0; die < sc->sc_ndie; die++) {
-                       for (irq = 0; irq < sc->sc_nirq; irq++) {
-                               ih = sc->sc_irq_handler[die][irq];
-                               if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
-                                       continue;
-                               aplintc_mask_set(sc, die, irq);
-                       }
-               }
-               break;
-       case DVACT_RESUME:
-               for (die = 0; die < sc->sc_ndie; die++) {
-                       for (irq = 0; irq < sc->sc_nirq; irq++) {
-                               ih = sc->sc_irq_handler[die][irq];
-                               if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
-                                       continue;
-                               aplintc_mask_clr(sc, die, irq);
-                       }
-               }
-               break;
-       }
-
-       return 0;
-}
-
 void
 aplintc_cpuinit(void)
 {
@@ -543,6 +511,40 @@ aplintc_setipl(int ipl)
        ci->ci_cpl = ipl;
 }
 
+void
+aplintc_enable_wakeup(void)
+{
+       struct aplintc_softc *sc = aplintc_sc;
+       struct intrhand *ih;
+       int die, irq;
+
+       for (die = 0; die < sc->sc_ndie; die++) {
+               for (irq = 0; irq < sc->sc_nirq; irq++) {
+                       ih = sc->sc_irq_handler[die][irq];
+                       if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
+                               continue;
+                       aplintc_mask_set(sc, die, irq);
+               }
+       }
+}
+
+void
+aplintc_disable_wakeup(void)
+{
+       struct aplintc_softc *sc = aplintc_sc;
+       struct intrhand *ih;
+       int die, irq;
+
+       for (die = 0; die < sc->sc_ndie; die++) {
+               for (irq = 0; irq < sc->sc_nirq; irq++) {
+                       ih = sc->sc_irq_handler[die][irq];
+                       if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
+                               continue;
+                       aplintc_mask_clr(sc, die, irq);
+               }
+       }
+}
+
 void *
 aplintc_intr_establish(void *cookie, int *cell, int level,
     struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
@@ -638,7 +640,7 @@ aplintc_intr_disestablish(void *cookie)
 }
 
 void
-aplintc_intr_enable_wakeup(void *cookie)
+aplintc_intr_set_wakeup(void *cookie)
 {
        struct intrhand *ih = cookie;
 
index fe3a99d..3437300 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplmbox.c,v 1.4 2022/12/03 13:42:23 kettenis Exp $    */
+/*     $OpenBSD: aplmbox.c,v 1.5 2022/12/21 22:30:42 kettenis Exp $    */
 /*
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -149,7 +149,7 @@ aplmbox_channel(void *cookie, uint32_t *cells, struct mbox_client *mc)
                sc->sc_rx_arg = mc->mc_rx_arg;
 
                if (mc->mc_flags & MC_WAKEUP)
-                       intr_enable_wakeup(sc->sc_ih);
+                       intr_set_wakeup(sc->sc_ih);
        }
 
        return sc;
index 8467420..c244dd3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcm2836_intr.c,v 1.14 2022/01/02 20:00:21 kettenis Exp $ */
+/* $OpenBSD: bcm2836_intr.c,v 1.15 2022/12/21 22:30:42 kettenis Exp $ */
 /*
  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2015 Patrick Wildt <patrick@blueri.se>
@@ -211,7 +211,8 @@ bcm_intc_attach(struct device *parent, struct device *self, void *aux)
 
        /* insert self as interrupt handler */
        arm_set_intr_handler(bcm_intc_splraise, bcm_intc_spllower,
-           bcm_intc_splx, bcm_intc_setipl, bcm_intc_irq_handler, NULL);
+           bcm_intc_splx, bcm_intc_setipl, bcm_intc_irq_handler, NULL,
+           NULL, NULL);
 
        sc->sc_intc.ic_node = faa->fa_node;
        sc->sc_intc.ic_cookie = sc;
index c42518a..0f1da4d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: intr.h,v 1.20 2022/11/09 19:18:11 kettenis Exp $ */
+/*     $OpenBSD: intr.h,v 1.21 2022/12/21 22:30:42 kettenis Exp $ */
 
 /*
  * Copyright (c) 2001-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
@@ -88,7 +88,8 @@ void  splx(int);
 
 void   arm_do_pending_intr(int);
 void   arm_set_intr_handler(int (*)(int), int (*)(int), void (*)(int),
-           void (*)(int), void (*)(void *), void (*)(void *));
+           void (*)(int), void (*)(void *), void (*)(void *),
+           void (*)(void), void (*)(void));
 
 struct machine_intr_handle {
        struct interrupt_controller *ih_ic;
@@ -100,6 +101,8 @@ struct arm_intr_func {
        int (*lower)(int);
        void (*x)(int);
        void (*setipl)(int);
+       void (*enable_wakeup)(void);
+       void (*disable_wakeup)(void);
 };
 
 extern struct arm_intr_func arm_intr_func;
@@ -126,7 +129,9 @@ extern struct arm_intr_func arm_intr_func;
 #define        spl0()          spllower(IPL_NONE)
 
 void    intr_barrier(void *);
-void    intr_enable_wakeup(void *);
+void    intr_set_wakeup(void *);
+void    intr_enable_wakeup(void);
+void    intr_disable_wakeup(void);
 
 void    arm_init_smask(void); /* XXX */
 extern uint32_t arm_smask[NIPL];
@@ -152,7 +157,7 @@ struct interrupt_controller {
        void     (*ic_route)(void *, int, struct cpu_info *);
        void     (*ic_cpu_enable)(void);
        void     (*ic_barrier)(void *);
-       void     (*ic_enable_wakeup)(void *);
+       void     (*ic_set_wakeup)(void *);
 
        LIST_ENTRY(interrupt_controller) ic_list;
        uint32_t ic_phandle;