1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-18 15:30:21 +00:00

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.
This commit is contained in:
Svatopluk Kraus 2016-04-07 15:00:25 +00:00
parent c8a8eb16e0
commit 5b613c19b5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297674
4 changed files with 40 additions and 42 deletions

View File

@ -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

View File

@ -525,40 +525,21 @@ bcm_lintc_setup_intr(device_t dev, struct intr_irqsrc *isrc,
}
#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));

View File

@ -467,6 +467,32 @@ intr_isrc_deregister(struct intr_irqsrc *isrc)
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)
{

View File

@ -98,6 +98,10 @@ int intr_isrc_deregister(struct intr_irqsrc *);
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);