Bring over the changes I made to the armv7 version of this driver such that
authorkettenis <kettenis@openbsd.org>
Sat, 8 Apr 2017 22:31:33 +0000 (22:31 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 8 Apr 2017 22:31:33 +0000 (22:31 +0000)
interrupts are correctly routed to the boot cpu if that isn't the one
connected to CPU interface zero on the interrupt controller.

ok patrick@

sys/arch/arm64/dev/ampintc.c

index 1195320..acca8ac 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ampintc.c,v 1.7 2017/02/25 17:04:19 patrick Exp $ */
+/* $OpenBSD: ampintc.c,v 1.8 2017/04/08 22:31:33 kettenis Exp $ */
 /*
  * Copyright (c) 2007,2009,2011 Dale Rahn <drahn@openbsd.org>
  *
@@ -138,6 +138,7 @@ struct ampintc_softc {
        int                      sc_nintr;
        bus_space_tag_t          sc_iot;
        bus_space_handle_t       sc_d_ioh, sc_p_ioh;
+       uint8_t                  sc_cpu_mask[ICD_ICTR_CPU_M + 1];
        struct evcount           sc_spur;
        struct interrupt_controller sc_ic;
 };
@@ -184,7 +185,7 @@ void                 ampintc_set_priority(int, int);
 void            ampintc_intr_enable(int);
 void            ampintc_intr_disable(int);
 void            ampintc_intr_config(int, int);
-void            ampintc_route(int, int , int);
+void            ampintc_route(int, int, struct cpu_info *);
 
 struct cfattach        ampintc_ca = {
        sizeof (struct ampintc_softc), ampintc_match, ampintc_attach
@@ -220,7 +221,8 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
 {
        struct ampintc_softc *sc = (struct ampintc_softc *)self;
        struct fdt_attach_args *faa = aux;
-       int i, nintr;
+       int i, nintr, ncpu;
+       uint32_t ictr;
 
        ampintc = sc;
 
@@ -240,11 +242,16 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
 
        evcount_attach(&sc->sc_spur, "irq1023/spur", NULL);
 
-       nintr = 32 * (bus_space_read_4(sc->sc_iot, sc->sc_d_ioh,
-           ICD_ICTR) & ICD_ICTR_ITL_M);
+       ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
+       nintr = 32 * ((ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M);
        nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */
        sc->sc_nintr = nintr;
-       printf(" nirq %d", nintr);
+       ncpu = ((ictr >> ICD_ICTR_CPU_SH) & ICD_ICTR_CPU_M) + 1;
+       printf(" nirq %d, ncpu %d", nintr, ncpu);
+
+       KASSERT(curcpu()->ci_cpuid <= ICD_ICTR_CPU_M);
+       sc->sc_cpu_mask[curcpu()->ci_cpuid] =
+           bus_space_read_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(0));
 
        /* Disable all interrupts, clear all pending */
        for (i = 0; i < nintr/32; i++) {
@@ -403,11 +410,10 @@ ampintc_calc_mask(void)
                if (min != IPL_NONE) {
                        ampintc_set_priority(irq, min);
                        ampintc_intr_enable(irq);
-                       ampintc_route(irq, IRQ_ENABLE, 0);
+                       ampintc_route(irq, IRQ_ENABLE, ci);
                } else {
                        ampintc_intr_disable(irq);
-                       ampintc_route(irq, IRQ_DISABLE, 0);
-
+                       ampintc_route(irq, IRQ_DISABLE, ci);
                }
        }
        ampintc_setipl(ci->ci_cpl);
@@ -476,16 +482,19 @@ ampintc_eoi(uint32_t eoi)
 }
 
 void
-ampintc_route(int irq, int enable, int cpu)
+ampintc_route(int irq, int enable, struct cpu_info *ci)
 {
-       uint8_t  val;
        struct ampintc_softc    *sc = ampintc;
+       uint8_t                  mask, val;
+
+       KASSERT(ci->ci_cpuid <= ICD_ICTR_CPU_M);
+       mask = sc->sc_cpu_mask[ci->ci_cpuid];
 
        val = bus_space_read_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(irq));
        if (enable == IRQ_ENABLE)
-               val |= (1 << cpu);
+               val |= mask;
        else
-               val &= ~(1 << cpu);
+               val &= ~mask;
        bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(irq), val);
 }