Skip to content
This repository was archived by the owner on Nov 11, 2024. It is now read-only.

Commit 05de606

Browse files
Marc Zyngiergregkh
authored andcommitted
irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
[ Upstream commit dd098a0e031928cf88c89f7577d31821e1f0e6de ] The MIPS GIC driver uses irq_cpu_online() to go and program the per-CPU interrupts. However, this method iterates over all IRQs in the system, despite only 3 per-CPU interrupts being of interest. Let's be terribly bold and do the iteration ourselves. To ensure mutual exclusion, hold the gic_lock spinlock that is otherwise taken while dealing with these interrupts. Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Serge Semin <fancer.lancer@gmail.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Tested-by: Serge Semin <fancer.lancer@gmail.com> Link: https://lore.kernel.org/r/20211021170414.3341522-3-maz@kernel.org Stable-dep-of: 3d6a0e4197c0 ("irqchip/mips-gic: Use raw spinlock for gic_lock") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 1224e5a commit 05de606

1 file changed

Lines changed: 26 additions & 11 deletions

File tree

drivers/irqchip/irq-mips-gic.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -380,24 +380,35 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
380380
spin_unlock_irqrestore(&gic_lock, flags);
381381
}
382382

383-
static void gic_all_vpes_irq_cpu_online(struct irq_data *d)
383+
static void gic_all_vpes_irq_cpu_online(void)
384384
{
385-
struct gic_all_vpes_chip_data *cd;
386-
unsigned int intr;
385+
static const unsigned int local_intrs[] = {
386+
GIC_LOCAL_INT_TIMER,
387+
GIC_LOCAL_INT_PERFCTR,
388+
GIC_LOCAL_INT_FDC,
389+
};
390+
unsigned long flags;
391+
int i;
387392

388-
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
389-
cd = irq_data_get_irq_chip_data(d);
393+
spin_lock_irqsave(&gic_lock, flags);
390394

391-
write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
392-
if (cd->mask)
393-
write_gic_vl_smask(BIT(intr));
395+
for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
396+
unsigned int intr = local_intrs[i];
397+
struct gic_all_vpes_chip_data *cd;
398+
399+
cd = &gic_all_vpes_chip_data[intr];
400+
write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
401+
if (cd->mask)
402+
write_gic_vl_smask(BIT(intr));
403+
}
404+
405+
spin_unlock_irqrestore(&gic_lock, flags);
394406
}
395407

396408
static struct irq_chip gic_all_vpes_local_irq_controller = {
397409
.name = "MIPS GIC Local",
398410
.irq_mask = gic_mask_local_irq_all_vpes,
399411
.irq_unmask = gic_unmask_local_irq_all_vpes,
400-
.irq_cpu_online = gic_all_vpes_irq_cpu_online,
401412
};
402413

403414
static void __gic_irq_dispatch(void)
@@ -476,6 +487,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
476487
intr = GIC_HWIRQ_TO_LOCAL(hwirq);
477488
map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin;
478489

490+
/*
491+
* If adding support for more per-cpu interrupts, keep the the
492+
* array in gic_all_vpes_irq_cpu_online() in sync.
493+
*/
479494
switch (intr) {
480495
case GIC_LOCAL_INT_TIMER:
481496
/* CONFIG_MIPS_CMP workaround (see __gic_init) */
@@ -662,8 +677,8 @@ static int gic_cpu_startup(unsigned int cpu)
662677
/* Clear all local IRQ masks (ie. disable all local interrupts) */
663678
write_gic_vl_rmask(~0);
664679

665-
/* Invoke irq_cpu_online callbacks to enable desired interrupts */
666-
irq_cpu_online();
680+
/* Enable desired interrupts */
681+
gic_all_vpes_irq_cpu_online();
667682

668683
return 0;
669684
}

0 commit comments

Comments
 (0)