| From e1044ceb41d9927df544a39ac02f5b1a8e4cc488 Mon Sep 17 00:00:00 2001 |
| From: Florian Fainelli <f.fainelli@gmail.com> |
| Date: Mon, 31 Oct 2016 14:17:35 -0700 |
| Subject: [PATCH] irqchip/bcm7038-l1: Implement irq_cpu_offline() callback |
| |
| commit 34c535793bcbf9263cf22f8a52101f796cdfab8e upstream. |
| |
| We did not implement an irq_cpu_offline callback for our irqchip, yet we |
| support setting a given IRQ's affinity. This resulted in interrupts |
| whose affinity mask included CPUs being taken offline not to work |
| correctly once the CPU had been put offline. |
| |
| Fixes: 5f7f0317ed28 ("IRQCHIP: Add new driver for BCM7038-style level 1 interrupt controllers") |
| Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> |
| Cc: linux-mips@linux-mips.org |
| Cc: jason@lakedaemon.net |
| Cc: marc.zyngier@arm.com |
| Cc: cernekee@gmail.com |
| Cc: jaedon.shin@gmail.com |
| Cc: ralf@linux-mips.org |
| Cc: justinpopo6@gmail.com |
| Link: http://lkml.kernel.org/r/1477948656-12966-2-git-send-email-f.fainelli@gmail.com |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c |
| index 0fea985ef1dc..d7af88534971 100644 |
| --- a/drivers/irqchip/irq-bcm7038-l1.c |
| +++ b/drivers/irqchip/irq-bcm7038-l1.c |
| @@ -216,6 +216,31 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, |
| return 0; |
| } |
| |
| +static void bcm7038_l1_cpu_offline(struct irq_data *d) |
| +{ |
| + struct cpumask *mask = irq_data_get_affinity_mask(d); |
| + int cpu = smp_processor_id(); |
| + cpumask_t new_affinity; |
| + |
| + /* This CPU was not on the affinity mask */ |
| + if (!cpumask_test_cpu(cpu, mask)) |
| + return; |
| + |
| + if (cpumask_weight(mask) > 1) { |
| + /* |
| + * Multiple CPU affinity, remove this CPU from the affinity |
| + * mask |
| + */ |
| + cpumask_copy(&new_affinity, mask); |
| + cpumask_clear_cpu(cpu, &new_affinity); |
| + } else { |
| + /* Only CPU, put on the lowest online CPU */ |
| + cpumask_clear(&new_affinity); |
| + cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); |
| + } |
| + irq_set_affinity_locked(d, &new_affinity, false); |
| +} |
| + |
| static int __init bcm7038_l1_init_one(struct device_node *dn, |
| unsigned int idx, |
| struct bcm7038_l1_chip *intc) |
| @@ -267,6 +292,7 @@ static struct irq_chip bcm7038_l1_irq_chip = { |
| .irq_mask = bcm7038_l1_mask, |
| .irq_unmask = bcm7038_l1_unmask, |
| .irq_set_affinity = bcm7038_l1_set_affinity, |
| + .irq_cpu_offline = bcm7038_l1_cpu_offline, |
| }; |
| |
| static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, |
| -- |
| 2.10.1 |
| |