Commit 1e4e873c authored by Dietmar Eggemann's avatar Dietmar Eggemann
Browse files

arm: fix a migrating irq bug when hotplug cpu

Arm TC2 fails cpu hotplug stress test.

This issue was tracked down to a missing copy of the new affinity
cpumask for the vexpress-spc interrupt into struct
irq_common_data.affinity when the interrupt is migrated in

Fix it by replacing the arm specific hotplug cpu migration with the
generic irq code.

This is the counterpart implementation to commit 217d453d

fix a migrating irq bug when hotplug cpu").

Tested with cpu hotplug stress test on Arm TC2 (multi_v7_defconfig plus
The vexpress-spc interrupt (irq=22) on this board is affine to CPU0.
Its affinity cpumask now changes correctly e.g. from 0 to 1-4 when
CPU0 is hotplugged out.
Suggested-by: default avatarMarc Zyngier <>
Signed-off-by: Dietmar Eggemann's avatarDietmar Eggemann <>
Acked-by: default avatarMarc Zyngier <>
Reviewed-by: default avatarLinus Walleij <>
parent 49a57857
......@@ -1400,6 +1400,7 @@ config NR_CPUS
bool "Support for hot-pluggable CPUs"
depends on SMP
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
......@@ -25,7 +25,6 @@
#ifndef __ASSEMBLY__
struct irqaction;
struct pt_regs;
extern void migrate_irqs(void);
extern void asm_do_IRQ(unsigned int, struct pt_regs *);
void handle_IRQ(unsigned int, struct pt_regs *);
......@@ -31,7 +31,6 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/ratelimit.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/kallsyms.h>
......@@ -109,64 +108,3 @@ int __init arch_probe_nr_irqs(void)
return nr_irqs;
static bool migrate_one_irq(struct irq_desc *desc)
struct irq_data *d = irq_desc_get_irq_data(desc);
const struct cpumask *affinity = irq_data_get_affinity_mask(d);
struct irq_chip *c;
bool ret = false;
* If this is a per-CPU interrupt, or the affinity does not
* include this CPU, then we have nothing to do.
if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
return false;
if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
affinity = cpu_online_mask;
ret = true;
c = irq_data_get_irq_chip(d);
if (!c->irq_set_affinity)
pr_debug("IRQ%u: unable to set affinity\n", d->irq);
else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
cpumask_copy(irq_data_get_affinity_mask(d), affinity);
return ret;
* The current CPU has been marked offline. Migrate IRQs off this CPU.
* If the affinity settings do not allow other CPUs, force them onto any
* available CPU.
* Note: we must iterate over all IRQs, whether they have an attached
* action structure or not, as we need to get chained interrupts too.
void migrate_irqs(void)
unsigned int i;
struct irq_desc *desc;
unsigned long flags;
for_each_irq_desc(i, desc) {
bool affinity_broken;
affinity_broken = migrate_one_irq(desc);
if (affinity_broken)
pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n",
i, smp_processor_id());
......@@ -254,7 +254,7 @@ int __cpu_disable(void)
* OK - migrate IRQs away from this CPU
* Flush user cache and TLB mappings, and then remove this CPU
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment