From: Jianmin Lv lvjianmin@loongson.cn
LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7362E
--------------------------------
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn Signed-off-by: Juxin Gao gaojuxin@loongson.cn --- arch/loongarch/Kconfig | 1 - arch/loongarch/include/asm/irq.h | 1 + arch/loongarch/kernel/irq.c | 36 ++++++++++++++++++++++++++++++++ arch/loongarch/kernel/smp.c | 3 +-- kernel/irq/Kconfig | 4 ++-- 5 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 17d845edd8a7..306871d0f2b0 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -428,7 +428,6 @@ config SMP config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP - select GENERIC_IRQ_MIGRATION help Say Y here to allow turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 94a8f5743ba7..ce2b56665f46 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -120,6 +120,7 @@ extern struct fwnode_handle *pch_lpc_handle; extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
extern irqreturn_t loongson_ipi_interrupt(int irq, void *dev); +extern void fixup_irqs(void);
#include <asm-generic/irq.h>
diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 22562bb6fdc4..a1c1d9576393 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -96,6 +96,42 @@ static int __init get_ipi_irq(void) return -EINVAL; }
+#ifdef CONFIG_HOTPLUG_CPU +static void handle_irq_affinity(void) +{ + struct irq_desc *desc; + struct irq_chip *chip; + unsigned int irq; + unsigned long flags; + struct cpumask *affinity; + + for_each_active_irq(irq) { + desc = irq_to_desc(irq); + if (!desc) + continue; + + raw_spin_lock_irqsave(&desc->lock, flags); + + affinity = desc->irq_data.common->affinity; + if (!cpumask_intersects(affinity, cpu_online_mask)) + cpumask_copy(affinity, cpu_online_mask); + + chip = irq_data_get_irq_chip(&desc->irq_data); + if (chip && chip->irq_set_affinity) + chip->irq_set_affinity(&desc->irq_data, + desc->irq_data.common->affinity, true); + raw_spin_unlock_irqrestore(&desc->lock, flags); + } +} + +void fixup_irqs(void) +{ + handle_irq_affinity(); + irq_cpu_offline(); + clear_csr_ecfg(ECFG0_IM); +} +#endif + void __init init_IRQ(void) { int i, ret; diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index f5959f8ce1f8..c010d715d2a3 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -304,8 +304,7 @@ int loongson_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); local_irq_save(flags); - irq_migrate_all_off_this_cpu(); - clear_csr_ecfg(ECFG0_IM); + fixup_irqs(); local_irq_restore(flags); local_flush_tlb_all();
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 2531f3496ab6..8a65b0c34b5a 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig @@ -148,5 +148,5 @@ config GENERIC_IRQ_MULTI_HANDLER # Do not even think of enabling this on any new platform config DEPRECATED_IRQ_CPU_ONOFFLINE bool - depends on CAVIUM_OCTEON_SOC - default CAVIUM_OCTEON_SOC + depends on CAVIUM_OCTEON_SOC || LOONGARCH + default CAVIUM_OCTEON_SOC || LOONGARCH