Skip to content

Commit dd098a0

Browse files
author
Marc Zyngier
committed
irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
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 <[email protected]> Reviewed-by: Serge Semin <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Tested-by: Serge Semin <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent eb54113 commit dd098a0

File tree

1 file changed

+26
-11
lines changed

1 file changed

+26
-11
lines changed

drivers/irqchip/irq-mips-gic.c

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

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

389-
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
390-
cd = irq_data_get_irq_chip_data(d);
394+
spin_lock_irqsave(&gic_lock, flags);
391395

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

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

404415
static void __gic_irq_dispatch(void)
@@ -477,6 +488,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
477488
intr = GIC_HWIRQ_TO_LOCAL(hwirq);
478489
map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin;
479490

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

666-
/* Invoke irq_cpu_online callbacks to enable desired interrupts */
667-
irq_cpu_online();
681+
/* Enable desired interrupts */
682+
gic_all_vpes_irq_cpu_online();
668683

669684
return 0;
670685
}

0 commit comments

Comments
 (0)