svn commit: r297674 - in head/sys: arm/arm arm/broadcom/bcm2835 kern sys
Svatopluk Kraus
skra at FreeBSD.org
Thu Apr 7 15:00:27 UTC 2016
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);
More information about the svn-src-head
mailing list