From 5b58b6c4bf4d69b181c4bb706a9d435a20c86f31 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 19 Mar 2025 03:19:57 +0000 Subject: [PATCH] anolis: sw64: msi: fix irq affinity setting during migration ANBZ: #4688 When a managed irq's last active cpu in its affinity mask is offline, interrupts remain disabled until another cpu in the affinity comes online. Frequent cpu hotplug operations exacerbate this issue by progressively narrowing the affinity mask, reducing the available cpu pool for recovery. To address this, we retain the original affinity during migration and introduce effective affinity through the irq_data_update_effective_affinity. This approach achieves the following benefits: 1. Maintains a larger candidate cpu pool based on the original affinity. 2. Allows interrupts to resume as soon as any cpu in the original affinity set comes online. 3. Mitigates dependency on specific cpus coming online quickly. This solution ensures more robust interrupt handing under dynamic cpu configurations while preserving system responsiveness. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + drivers/irqchip/irq-sunway-msi-v2.c | 18 +++++++++++------- drivers/irqchip/irq-sunway-msi.c | 17 ++++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index f52bea4d7fc4..cad00781aa8c 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -62,6 +62,7 @@ config SW64 select GENERIC_ARCH_TOPOLOGY select GENERIC_CLOCKEVENTS select GENERIC_IRQ_LEGACY + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP select GENERIC_IRQ_MIGRATION if SMP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 70d0da9f0cc9..0af47decaf6c 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -137,22 +137,24 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, irqd = irq_domain_get_irq_data(msi_default_domain->parent, d->irq); /* Don't do anything if the interrupt isn't started */ - if (!irqd_is_started(irqd)) + if (!irqd_is_started(irqd) && !irqd_affinity_is_managed(irqd)) return IRQ_SET_MASK_OK; cdata = irqd->chip_data; if (!cdata) return -ENOMEM; - if (cdata->move_in_progress) - return -EBUSY; - /* * If existing target cpu is already in the new mask and is online * then do nothing. */ - if (cpu_online(cdata->dst_cpu) && cpumask_test_cpu(cdata->dst_cpu, cpumask)) - return IRQ_SET_MASK_OK; + if (cpu_online(cdata->dst_cpu)) { + if (cpumask_test_cpu(cdata->dst_cpu, cpumask)) + return IRQ_SET_MASK_OK; + + if (cdata->move_in_progress) + return -EBUSY; + } raw_spin_lock_irqsave(&vector_lock, flags); @@ -190,7 +192,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, irq_msi_compose_msg(d, &msg); __pci_write_msi_msg(entry, &msg); spin_unlock(&cdata->cdata_lock); - cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); raw_spin_unlock_irqrestore(&vector_lock, flags); @@ -259,6 +261,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, } irq_data->chip_data = cdata; + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); } cdata->dst_cpu = cpu; @@ -295,6 +298,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, cdata->prev_vector = vector; cdata->multi_msi = 1; cdata->move_in_progress = false; + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); } } return 0; diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 6871248ad124..d94492049a04 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -113,22 +113,24 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, irqd = irq_domain_get_irq_data(msi_default_domain->parent, d->irq); /* Don't do anything if the interrupt isn't started */ - if (!irqd_is_started(irqd)) + if (!irqd_is_started(irqd) && !irqd_affinity_is_managed(irqd)) return IRQ_SET_MASK_OK; cdata = irqd->chip_data; if (!cdata) return -ENOMEM; - if (cdata->move_in_progress) - return -EBUSY; - /* * If existing target cpu is already in the new mask and is online * then do nothing. */ - if (cpu_online(cdata->dst_cpu) && cpumask_test_cpu(cdata->dst_cpu, cpumask)) - return IRQ_SET_MASK_OK; + if (cpu_online(cdata->dst_cpu)) { + if (cpumask_test_cpu(cdata->dst_cpu, cpumask)) + return IRQ_SET_MASK_OK; + + if (cdata->move_in_progress) + return -EBUSY; + } raw_spin_lock_irqsave(&vector_lock, flags); @@ -157,7 +159,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector); cdata->msi_config = msi_config; spin_unlock(&cdata->cdata_lock); - cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); raw_spin_unlock_irqrestore(&vector_lock, flags); @@ -247,6 +249,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, cdata->prev_cpu = cpu; cdata->prev_vector = vector; cdata->move_in_progress = false; + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); } return 0; } -- Gitee