Skip to content

Commit 4cfffcf

Browse files
MJNowakowskiMarc Zyngier
authored andcommitted
irqchip/mips-gic: Fix local interrupts
Some local interrupts are not initialised properly at the moment and cannot be used since the domain's alloc method is never called for them. This has been observed earlier and partially fixed in commit e875bd6 ("irqchip/mips-gic: Fix local interrupts"), but that change still relied on the interrupt to be requested by an external driver (eg. drivers/clocksource/mips-gic-timer.c). This does however not solve the issue for interrupts that are not referenced by any driver through the device tree and results in request_irq() calls returning -ENOSYS. It can be observed when attempting to use perf tool to access hardware performance counters. Fix this by explicitly calling irq_create_fwspec_mapping() for local interrupts. Fixes: e875bd6 ("irqchip/mips-gic: Fix local interrupts") Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: linux-mips@linux-mips.org Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent b4d3053 commit 4cfffcf

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

drivers/irqchip/irq-mips-gic.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,34 @@ static struct irq_domain_ops gic_ipi_domain_ops = {
968968
.match = gic_ipi_domain_match,
969969
};
970970

971+
static void __init gic_map_single_int(struct device_node *node,
972+
unsigned int irq)
973+
{
974+
unsigned int linux_irq;
975+
struct irq_fwspec local_int_fwspec = {
976+
.fwnode = &node->fwnode,
977+
.param_count = 3,
978+
.param = {
979+
[0] = GIC_LOCAL,
980+
[1] = irq,
981+
[2] = IRQ_TYPE_NONE,
982+
},
983+
};
984+
985+
if (!gic_local_irq_is_routable(irq))
986+
return;
987+
988+
linux_irq = irq_create_fwspec_mapping(&local_int_fwspec);
989+
WARN_ON(!linux_irq);
990+
}
991+
992+
static void __init gic_map_interrupts(struct device_node *node)
993+
{
994+
gic_map_single_int(node, GIC_LOCAL_INT_TIMER);
995+
gic_map_single_int(node, GIC_LOCAL_INT_PERFCTR);
996+
gic_map_single_int(node, GIC_LOCAL_INT_FDC);
997+
}
998+
971999
static void __init __gic_init(unsigned long gic_base_addr,
9721000
unsigned long gic_addrspace_size,
9731001
unsigned int cpu_vec, unsigned int irqbase,
@@ -1067,6 +1095,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
10671095
}
10681096

10691097
gic_basic_init();
1098+
gic_map_interrupts(node);
10701099
}
10711100

10721101
void __init gic_init(unsigned long gic_base_addr,

0 commit comments

Comments
 (0)