aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2015-03-03 05:27:23 -0500
committerJason Cooper <jason@lakedaemon.net>2015-03-07 22:58:55 -0500
commit5724be8464dceac047c1eaddaa3651cea0ec16ca (patch)
tree572be804300f984f2143ef71ab5c0db2d40ba992
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
irqchip: armada-370-xp: Fix chained per-cpu interrupts
On the Cortex-A9-based Armada SoCs, the MPIC is not the primary interrupt controller. Yet, it still has to handle some per-cpu interrupt. To do so, it is chained with the GIC using a per-cpu interrupt. However, the current code only call irq_set_chained_handler, which is called and enable that interrupt only on the boot CPU, which means that the parent per-CPU interrupt is never unmasked on the secondary CPUs, preventing the per-CPU interrupt to actually work as expected. This was not seen until now since the only MPIC PPI users were the Marvell timers that were not working, but not used either since the system use the ARM TWD by default, and the ethernet controllers, that are faking there interrupts as SPI, and don't really expect to have interrupts on the secondary cores anyway. Add a CPU notifier that will enable the PPI on the secondary cores when they are brought up. Cc: <stable@vger.kernel.org> # 3.15+ Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Link: https://lkml.kernel.org/r/1425378443-28822-1-git-send-email-maxime.ripard@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 463c235acbdc..4387dae14e45 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -69,6 +69,7 @@ static void __iomem *per_cpu_int_base;
69static void __iomem *main_int_base; 69static void __iomem *main_int_base;
70static struct irq_domain *armada_370_xp_mpic_domain; 70static struct irq_domain *armada_370_xp_mpic_domain;
71static u32 doorbell_mask_reg; 71static u32 doorbell_mask_reg;
72static int parent_irq;
72#ifdef CONFIG_PCI_MSI 73#ifdef CONFIG_PCI_MSI
73static struct irq_domain *armada_370_xp_msi_domain; 74static struct irq_domain *armada_370_xp_msi_domain;
74static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); 75static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
@@ -356,6 +357,7 @@ static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
356{ 357{
357 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) 358 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
358 armada_xp_mpic_smp_cpu_init(); 359 armada_xp_mpic_smp_cpu_init();
360
359 return NOTIFY_OK; 361 return NOTIFY_OK;
360} 362}
361 363
@@ -364,6 +366,20 @@ static struct notifier_block armada_370_xp_mpic_cpu_notifier = {
364 .priority = 100, 366 .priority = 100,
365}; 367};
366 368
369static int mpic_cascaded_secondary_init(struct notifier_block *nfb,
370 unsigned long action, void *hcpu)
371{
372 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
373 enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
374
375 return NOTIFY_OK;
376}
377
378static struct notifier_block mpic_cascaded_cpu_notifier = {
379 .notifier_call = mpic_cascaded_secondary_init,
380 .priority = 100,
381};
382
367#endif /* CONFIG_SMP */ 383#endif /* CONFIG_SMP */
368 384
369static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { 385static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
@@ -539,7 +555,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
539 struct device_node *parent) 555 struct device_node *parent)
540{ 556{
541 struct resource main_int_res, per_cpu_int_res; 557 struct resource main_int_res, per_cpu_int_res;
542 int parent_irq, nr_irqs, i; 558 int nr_irqs, i;
543 u32 control; 559 u32 control;
544 560
545 BUG_ON(of_address_to_resource(node, 0, &main_int_res)); 561 BUG_ON(of_address_to_resource(node, 0, &main_int_res));
@@ -587,6 +603,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
587 register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier); 603 register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier);
588#endif 604#endif
589 } else { 605 } else {
606#ifdef CONFIG_SMP
607 register_cpu_notifier(&mpic_cascaded_cpu_notifier);
608#endif
590 irq_set_chained_handler(parent_irq, 609 irq_set_chained_handler(parent_irq,
591 armada_370_xp_mpic_handle_cascade_irq); 610 armada_370_xp_mpic_handle_cascade_irq);
592 } 611 }