Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/broadcom Handle processor private interrupts be...



details:   https://anonhg.NetBSD.org/src/rev/14ccbc992a1b
branches:  trunk
changeset: 449278:14ccbc992a1b
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Mar 01 14:53:12 2019 +0000

description:
Handle processor private interrupts better and add support for the PMU
interrupt.

Thanks to jmcneill for review and suggestions.

diffstat:

 sys/arch/arm/broadcom/bcm2835_intr.c |  149 +++++++++++++++++++++++++++++-----
 1 files changed, 126 insertions(+), 23 deletions(-)

diffs (247 lines):

diff -r d50818cce73d -r 14ccbc992a1b sys/arch/arm/broadcom/bcm2835_intr.c
--- a/sys/arch/arm/broadcom/bcm2835_intr.c      Fri Mar 01 12:25:09 2019 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_intr.c      Fri Mar 01 14:53:12 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_intr.c,v 1.18 2019/03/01 08:05:46 skrll Exp $  */
+/*     $NetBSD: bcm2835_intr.c,v 1.19 2019/03/01 14:53:12 skrll Exp $  */
 
 /*-
  * Copyright (c) 2012, 2015 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.18 2019/03/01 08:05:46 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.19 2019/03/01 14:53:12 skrll Exp $");
 
 #define _INTR_PRIVATE
 
@@ -40,6 +40,8 @@
 #include <sys/bus.h>
 #include <sys/cpu.h>
 #include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
 #include <sys/proc.h>
 
 #include <dev/fdt/fdtvar.h>
@@ -146,6 +148,20 @@
        .intrstr = bcm2836mp_icu_fdt_intrstr
 };
 
+struct bcm2836mp_interrupt {
+       bool bi_done;
+       TAILQ_ENTRY(bcm2836mp_interrupt) bi_next;
+       int bi_irq;
+       int bi_ipl;
+       int bi_flags;
+       int (*bi_func)(void *);
+       void *bi_arg;
+       void *bi_ihs[BCM2836_NCPUS];
+};
+
+static TAILQ_HEAD(, bcm2836mp_interrupt) bcm2836mp_interrupts =
+    TAILQ_HEAD_INITIALIZER(bcm2836mp_interrupts);
+
 struct bcm2835icu_softc {
        device_t                sc_dev;
        bus_space_tag_t         sc_iot;
@@ -450,20 +466,19 @@
 }
 
 #define        BCM2836MP_TIMER_IRQS    __BITS(3,0)
-#define        BCM2836MP_MAILBOX_IRQS  __BITS(4,4)
-
-#define        BCM2836MP_ALL_IRQS      (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS)
+#define        BCM2836MP_MAILBOX_IRQS  __BITS(4,7)
+#define        BCM2836MP_GPU_IRQ       __BIT(8)
+#define        BCM2836MP_PMU_IRQ       __BIT(9)
+#define        BCM2836MP_ALL_IRQS      (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS | BCM2836MP_GPU_IRQ | BCM2836MP_PMU_IRQ)
 
 static void
 bcm2836mp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
     uint32_t irq_mask)
 {
-       struct cpu_info * const ci = curcpu();
-       const cpuid_t cpuid = ci->ci_core_id;
        const bus_space_tag_t iot = bcml1icu_sc->sc_iot;
        const bus_space_handle_t ioh = bcml1icu_sc->sc_ioh;
+       const cpuid_t cpuid = pic - &bcm2836mp_pic[0];
 
-       KASSERT(pic == &bcm2836mp_pic[cpuid]);
        KASSERT(irqbase == 0);
 
        if (irq_mask & BCM2836MP_TIMER_IRQS) {
@@ -492,6 +507,12 @@
                    BCM2836_LOCAL_MAILBOX_IRQ_CONTROL_SIZE,
                    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
        }
+       if (irq_mask & BCM2836MP_PMU_IRQ) {
+               bus_space_write_4(iot, ioh, BCM2836_LOCAL_PM_ROUTING_SET,
+                   __BIT(cpuid));
+               bus_space_barrier(iot, ioh, BCM2836_LOCAL_PM_ROUTING_SET, 4,
+                   BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
+       }
 
        return;
 }
@@ -500,12 +521,10 @@
 bcm2836mp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
     uint32_t irq_mask)
 {
-       struct cpu_info * const ci = curcpu();
-       const cpuid_t cpuid = ci->ci_core_id;
        const bus_space_tag_t iot = bcml1icu_sc->sc_iot;
        const bus_space_handle_t ioh = bcml1icu_sc->sc_ioh;
+       const cpuid_t cpuid = pic - &bcm2836mp_pic[0];
 
-       KASSERT(pic == &bcm2836mp_pic[cpuid]);
        KASSERT(irqbase == 0);
 
        if (irq_mask & BCM2836MP_TIMER_IRQS) {
@@ -526,6 +545,10 @@
                    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid),
                    val);
        }
+       if (irq_mask & BCM2836MP_PMU_IRQ) {
+               bus_space_write_4(iot, ioh, BCM2836_LOCAL_PM_ROUTING_CLR,
+                    __BIT(cpuid));
+       }
 
        bcm2835_barrier();
        return;
@@ -656,14 +679,18 @@
 #if defined(MULTIPROCESSOR)
        intr_establish(BCM2836_INT_MAILBOX0_CPUN(cpuid), IPL_HIGH,
            IST_LEVEL | IST_MPSAFE, bcm2836mp_ipi_handler, NULL);
-#endif
-       /* clock interrupt will attach with gtmr */
-       if (cpuid == 0)
-               return;
-#if defined(SOC_BCM2836)
-       intr_establish(BCM2836_INT_CNTVIRQ_CPUN(cpuid), IPL_CLOCK,
-           IST_LEVEL | IST_MPSAFE, gtmr_intr, NULL);
+
+       struct bcm2836mp_interrupt *bip;
+       TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) {
+               if (bip->bi_done)
+                       continue;
 
+               const int irq = BCM2836_INT_BASECPUN(cpuid) + bip->bi_irq;
+               void *ih = intr_establish(irq, bip->bi_ipl,
+                   IST_LEVEL | bip->bi_flags, bip->bi_func, bip->bi_arg);
+
+               bip->bi_ihs[cpuid] = ih;
+       }
 #endif
 }
 
@@ -672,7 +699,7 @@
 {
        if (!specifier)
                return -1;
-       return be32toh(specifier[0]) + BCM2836_INT_LOCALBASE;
+       return be32toh(specifier[0]);
 }
 
 static void *
@@ -680,19 +707,95 @@
     int (*func)(void *), void *arg)
 {
        int iflags = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
-       int irq;
+       struct bcm2836mp_interrupt *bip;
+       void *ih;
 
-       irq = bcm2836mp_icu_fdt_decode_irq(specifier);
+       int irq = bcm2836mp_icu_fdt_decode_irq(specifier);
        if (irq == -1)
                return NULL;
 
-       return intr_establish(irq, ipl, IST_LEVEL | iflags, func, arg);
+       TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) {
+               if (irq == bip->bi_irq)
+                       return NULL;
+       }
+
+       bip = kmem_alloc(sizeof(*bip), KM_SLEEP);
+       if (bip == NULL)
+               return NULL;
+
+       bip->bi_done = false;
+       bip->bi_irq = irq;
+       bip->bi_ipl = ipl;
+       bip->bi_flags = IST_LEVEL | iflags;
+       bip->bi_func = func;
+       bip->bi_arg = arg;
+
+       /*
+        * If we're not cold and the BPs have been started then we can register the
+        * interupt for all CPUs now, e.g. PMU
+        */
+       if (!cold) {
+               for (cpuid_t cpuid = 0; cpuid < BCM2836_NCPUS; cpuid++) {
+                       ih = intr_establish(BCM2836_INT_BASECPUN(cpuid) + irq, ipl,
+                           IST_LEVEL | iflags, func, arg);
+                       if (!ih) {
+                               kmem_free(bip, sizeof(*bip));
+                               return NULL;
+                       }
+                       bip->bi_ihs[cpuid] = ih;
+
+               }
+               bip->bi_done = true;
+               ih = bip->bi_ihs[0];
+               goto done;
+       }
+
+       /*
+        * Otherwise we can only establish the interrupt for the BP and
+        * delay until bcm2836mp_intr_init is called for each AP, e.g.
+        * gtmr
+        */
+       ih = intr_establish(BCM2836_INT_BASECPUN(0) + irq, ipl,
+           IST_LEVEL | iflags, func, arg);
+       if (!ih) {
+               kmem_free(bip, sizeof(*bip));
+               return NULL;
+       }
+
+       bip->bi_ihs[0] = ih;
+       for (cpuid_t cpuid = 1; cpuid < BCM2836_NCPUS; cpuid++)
+               bip->bi_ihs[cpuid] = NULL;
+
+done:
+       TAILQ_INSERT_TAIL(&bcm2836mp_interrupts, bip, bi_next);
+
+       /*
+        * Return the intr_establish handle for cpu 0 for API compatibility.
+        * Any cpu would do here as these sources don't support set_affinity
+        * when the handle is used in interrupt_distribute(9)
+        */
+       return ih;
 }
 
 static void
 bcm2836mp_icu_fdt_disestablish(device_t dev, void *ih)
 {
-       intr_disestablish(ih);
+       struct bcm2836mp_interrupt *bip;
+
+       TAILQ_FOREACH(bip, &bcm2836mp_interrupts, bi_next) {
+               if (bip->bi_ihs[0] == ih)
+                       break;
+       }
+
+       if (bip == NULL)
+               return;
+
+       for (cpuid_t cpuid = 0; cpuid < BCM2836_NCPUS; cpuid++)
+               intr_disestablish(bip->bi_ihs[cpuid]);
+
+       TAILQ_REMOVE(&bcm2836mp_interrupts, bip, bi_next);
+
+       kmem_free(bip, sizeof(*bip));
 }
 
 static bool



Home | Main Index | Thread Index | Old Index