Author: skra
Date: Thu Apr  7 15:00:25 2016
New Revision: 297674
URL: https://svnweb.freebsd.org/changeset/base/297674

Log:
  Implement intr_isrc_init_on_cpu() and use it to replace very same
  code implemented in every interrupt controller driver running SMP.
  This function returns true, if provided ISRC should be enabled on
  given cpu.

Modified:
  head/sys/arm/arm/gic.c
  head/sys/arm/broadcom/bcm2835/bcm2836.c
  head/sys/kern/subr_intr.c
  head/sys/sys/intr.h

Modified: head/sys/arm/arm/gic.c
==============================================================================
--- head/sys/arm/arm/gic.c      Thu Apr  7 14:25:15 2016        (r297673)
+++ head/sys/arm/arm/gic.c      Thu Apr  7 15:00:25 2016        (r297674)
@@ -256,11 +256,11 @@ static void
 arm_gic_init_secondary(device_t dev)
 {
        struct arm_gic_softc *sc = device_get_softc(dev);
-       struct intr_irqsrc *isrc;
-       u_int irq;
+       u_int irq, cpu;
 
        /* Set the mask so we can find this CPU to send it IPIs */
-       arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
+       cpu = PCPU_GET(cpuid);
+       arm_gic_map[cpu] = gic_cpu_mask(sc);
 
        for (irq = 0; irq < sc->nirqs; irq += 4)
                gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0);
@@ -280,27 +280,14 @@ arm_gic_init_secondary(device_t dev)
        gic_d_write_4(sc, GICD_CTLR, 0x01);
 
        /* Unmask attached SGI interrupts. */
-       for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) {
-               isrc = GIC_INTR_ISRC(sc, irq);
-               if (isrc != NULL && isrc->isrc_handlers != 0) {
-                       CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
+       for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++)
+               if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu))
                        gic_irq_unmask(sc, irq);
-               }
-       }
 
        /* Unmask attached PPI interrupts. */
-       for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) {
-               isrc = GIC_INTR_ISRC(sc, irq);
-               if (isrc == NULL || isrc->isrc_handlers == 0)
-                       continue;
-               if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
-                       if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
-                               gic_irq_unmask(sc, irq);
-               } else {
-                       CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
+       for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++)
+               if (intr_isrc_init_on_cpu(GIC_INTR_ISRC(sc, irq), cpu))
                        gic_irq_unmask(sc, irq);
-               }
-       }
 }
 #else
 static void

Modified: head/sys/arm/broadcom/bcm2835/bcm2836.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2836.c     Thu Apr  7 14:25:15 2016        
(r297673)
+++ head/sys/arm/broadcom/bcm2835/bcm2836.c     Thu Apr  7 15:00:25 2016        
(r297674)
@@ -525,40 +525,21 @@ bcm_lintc_setup_intr(device_t dev, struc
 }
 
 #ifdef SMP
-static bool
-bcm_lint_init_on_ap(struct bcm_lintc_softc *sc, struct bcm_lintc_irqsrc *bli,
-    u_int cpu)
-{
-       struct intr_irqsrc *isrc;
-
-       isrc = &bli->bli_isrc;
-
-       KASSERT(isrc->isrc_flags & INTR_ISRCF_PPI,
-           ("%s: irq %d is not PPI", __func__, bli->bli_irq));
-
-       if (isrc->isrc_handlers == 0)
-               return (false);
-       if (isrc->isrc_flags & INTR_ISRCF_BOUND)
-               return (CPU_ISSET(cpu, &isrc->isrc_cpu));
-
-       CPU_SET(cpu, &isrc->isrc_cpu);
-       return (true);
-}
-
 static void
 bcm_lintc_init_rwreg_on_ap(struct bcm_lintc_softc *sc, u_int cpu, u_int irq,
     uint32_t reg, uint32_t mask)
 {
 
-       if (bcm_lint_init_on_ap(sc, &sc->bls_isrcs[irq], cpu))
+       if (intr_isrc_init_on_cpu(&sc->bls_isrcs[irq].bli_isrc, cpu))
                bcm_lintc_rwreg_set(sc, reg, mask);
 }
 
 static void
 bcm_lintc_init_pmu_on_ap(struct bcm_lintc_softc *sc, u_int cpu)
 {
+       struct intr_irqsrc *isrc = &sc->bls_isrcs[BCM_LINTC_PMU_IRQ].bli_isrc;
 
-       if (bcm_lint_init_on_ap(sc, &sc->bls_isrcs[BCM_LINTC_PMU_IRQ], cpu)) {
+       if (intr_isrc_init_on_cpu(isrc, cpu)) {
                /* Write-set register. */
                bcm_lintc_write_4(sc, BCM_LINTC_PMU_ROUTING_SET_REG,
                    BCM_LINTC_PIRR_IRQ_EN_CORE(cpu));

Modified: head/sys/kern/subr_intr.c
==============================================================================
--- head/sys/kern/subr_intr.c   Thu Apr  7 14:25:15 2016        (r297673)
+++ head/sys/kern/subr_intr.c   Thu Apr  7 15:00:25 2016        (r297674)
@@ -467,6 +467,32 @@ intr_isrc_deregister(struct intr_irqsrc 
        return (error);
 }
 
+#ifdef SMP
+/*
+ *  A support function for a PIC to decide if provided ISRC should be inited
+ *  on given cpu. The logic of INTR_ISRCF_BOUND flag and isrc_cpu member of
+ *  struct intr_irqsrc is the following:
+ *
+ *     If INTR_ISRCF_BOUND is set, the ISRC should be inited only on cpus
+ *     set in isrc_cpu. If not, the ISRC should be inited on every cpu and
+ *     isrc_cpu is kept consistent with it. Thus isrc_cpu is always correct.
+ */
+bool
+intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu)
+{
+
+       if (isrc->isrc_handlers == 0)
+               return (false);
+       if ((isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI)) == 0)
+               return (false);
+       if (isrc->isrc_flags & INTR_ISRCF_BOUND)
+               return (CPU_ISSET(cpu, &isrc->isrc_cpu));
+
+       CPU_SET(cpu, &isrc->isrc_cpu);
+       return (true);
+}
+#endif
+
 static struct intr_dev_data *
 intr_ddata_alloc(u_int extsize)
 {

Modified: head/sys/sys/intr.h
==============================================================================
--- head/sys/sys/intr.h Thu Apr  7 14:25:15 2016        (r297673)
+++ head/sys/sys/intr.h Thu Apr  7 15:00:25 2016        (r297674)
@@ -98,6 +98,10 @@ int intr_isrc_deregister(struct intr_irq
 int intr_isrc_register(struct intr_irqsrc *, device_t, u_int, const char *, 
...)
     __printflike(4, 5);
 
+#ifdef SMP
+bool intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu);
+#endif
+
 int intr_isrc_dispatch(struct intr_irqsrc *, struct trapframe *);
 u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to