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:
parent
c8a8eb16e0
commit
5b613c19b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297674
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user