From 7b119fd1bdc59a8060df5b659b9f7a70e0169fd6 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:04 +0100 Subject: irqchip: orion: clear bridge cause register on init It is good practice to mask and clear pending irqs on init. We already mask all irqs, so also clear the bridge irq cause register. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index e51d4003188..4137c3d1528 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -180,8 +180,9 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - /* mask all interrupts */ + /* mask and clear all interrupts */ writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK); + writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE); irq_set_handler_data(irq, domain); irq_set_chained_handler(irq, orion_bridge_irq_handler); -- cgit v1.2.3-70-g09d2 From 5f40067fc86f0e49329ad4a852c278998ff4394e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Thu, 23 Jan 2014 23:38:05 +0100 Subject: irqchip: orion: use handle_edge_irq on bridge irqs Bridge irqs are edge-triggered, i.e. they get asserted on low-to-high transitions and not on the level of the downstream interrupt line. This replaces handle_level_irq by the more appropriate handle_edge_irq. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 4137c3d1528..1f636f71906 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -143,7 +143,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, } ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name, - handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); + handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); if (ret) { pr_err("%s: unable to alloc irq domain gc\n", np->name); return ret; -- cgit v1.2.3-70-g09d2 From e0318ec3bf3f1502cd11b21b1eb00aa355b40b67 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Fri, 24 Jan 2014 00:10:32 +0100 Subject: irqchip: orion: clear stale interrupts in irq_startup Bridge IRQ_CAUSE bits are asserted regardless of the corresponding bit in IRQ_MASK register. To avoid interrupt events on stale irqs, we have to clear them before unmask. This installs an .irq_startup callback to ensure stale irqs are cleared before initial unmask. Signed-off-by: Sebastian Hesselbarth Tested-by: Ezequiel Garcia Cc: : f56c0738b5c2: "irqchip: orion: clear bridge cause register on init" Cc: : 38bd80b84fca: "irqchip: orion: use handle_edge_irq on bridge irqs" Cc: # v3.10+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 1f636f71906..0dfdc5c824a 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -123,6 +123,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) } } +/* + * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register. + * To avoid interrupt events on stale irqs, we clear them before unmask. + */ +static unsigned int orion_bridge_irq_startup(struct irq_data *d) +{ + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + ct->chip.irq_ack(d); + ct->chip.irq_unmask(d); + return 0; +} + static int __init orion_bridge_irq_init(struct device_node *np, struct device_node *parent) { @@ -176,6 +189,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE; gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; + gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup; gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; -- cgit v1.2.3-70-g09d2 From d86e9af6336c0ad586a5dbd70064253d40bbb5ff Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 7 Feb 2014 00:41:58 +0100 Subject: irqchip: orion: Fix getting generic chip pointer. Enabling SPARSE_IRQ shows up a bug in the irq-orion bridge interrupt handler. The bridge interrupt is implemented using a single generic chip. Thus the parameter passed to irq_get_domain_generic_chip() should always be zero. Signed-off-by: Andrew Lunn Acked-by: Sebastian Hesselbarth Fixes: 9dbd90f17e4f ("irqchip: Add support for Marvell Orion SoCs") Cc: # v3.11+ Signed-off-by: Jason Cooper --- drivers/irqchip/irq-orion.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 0dfdc5c824a..8e41be62812 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init); static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) { struct irq_domain *d = irq_get_handler_data(irq); - struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq); + + struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0); u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) & gc->mask_cache; -- cgit v1.2.3-70-g09d2 From f229006ec6beabf7b844653d92fa61f025fe3dcf Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 25 Feb 2014 22:05:35 +0000 Subject: irq-metag*: stop set_affinity vectoring to offline cpus Fix irq_set_affinity callbacks in the Meta IRQ chip drivers to AND cpu_online_mask into the cpumask when picking a CPU to vector the interrupt to. As Thomas pointed out, the /proc/irq/$N/smp_affinity interface doesn't filter out offline CPUs, so without this patch if you offline CPU0 and set an IRQ affinity to 0x3 it vectors the interrupt onto CPU0 even though it is offline. Reported-by: Thomas Gleixner Signed-off-by: James Hogan Cc: Thomas Gleixner Cc: linux-metag@vger.kernel.org Cc: stable@vger.kernel.org --- drivers/irqchip/irq-metag-ext.c | 2 +- drivers/irqchip/irq-metag.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/irqchip') diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c index 92c41ab4dbf..2cb474ad880 100644 --- a/drivers/irqchip/irq-metag-ext.c +++ b/drivers/irqchip/irq-metag-ext.c @@ -515,7 +515,7 @@ static int meta_intc_set_affinity(struct irq_data *data, * one cpu (the interrupt code doesn't support it), so we just * pick the first cpu we find in 'cpumask'. */ - cpu = cpumask_any(cpumask); + cpu = cpumask_any_and(cpumask, cpu_online_mask); thread = cpu_2_hwthread_id[cpu]; metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); diff --git a/drivers/irqchip/irq-metag.c b/drivers/irqchip/irq-metag.c index 8e94d7a3b20..c16c186d97d 100644 --- a/drivers/irqchip/irq-metag.c +++ b/drivers/irqchip/irq-metag.c @@ -201,7 +201,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data, * one cpu (the interrupt code doesn't support it), so we just * pick the first cpu we find in 'cpumask'. */ - cpu = cpumask_any(cpumask); + cpu = cpumask_any_and(cpumask, cpu_online_mask); thread = cpu_2_hwthread_id[cpu]; metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), -- cgit v1.2.3-70-g09d2