[PATCH OLK-6.6] irqdomain: Fix driver re-inserting failures when IRQs not being freed

driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9ERMB ------------------------------------------------------------------------ Since commit 4615fbc3788d ("genirq/irqdomain: Don't try to free an interrupt that has no mapping"), we have found failures when re-inserting some specific drivers: [root@localhost ~]# rmmod hisi_sas_v3_hw [root@localhost ~]# modprobe hisi_sas_v3_hw [ 1295.622525] hisi_sas_v3_hw: probe of 0000:30:04.0 failed with error -2 A relevant discussion can be found at: https://lore.kernel.org/lkml/3d3d0155e66429968cb4f6b4feeae4b3@kernel.org/ This is because IRQs from a low-level domain are not freed together, leaving some leaked. Thus, the next driver insertion fails to allocate the same number of IRQs. Free a contiguous group of IRQs in one go to fix this issue. Fixes: 4615fbc3788d ("genirq/irqdomain: Don't try to free an interrupt that has no mapping") Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com> Reviewed-by: Liao Chang <liaochang1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> --- kernel/irq/irqdomain.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 0bdef4fe925b..2ec5bd39635c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1443,13 +1443,24 @@ static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain, unsigned int nr_irqs) { unsigned int i; + int n; if (!domain->ops->free) return; for (i = 0; i < nr_irqs; i++) { - if (irq_domain_get_irq_data(domain, irq_base + i)) - domain->ops->free(domain, irq_base + i, 1); + /* Find the largest possible span of IRQs to free in one go */ + for (n = 0; + ((i + n) < nr_irqs) && + (irq_domain_get_irq_data(domain, irq_base + i + n)); + n++) + ; + + if (!n) + continue; + + domain->ops->free(domain, irq_base + i, n); + i += n; } } -- 2.30.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/5774 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/W... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/5774 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/W...

Hi: We only rebase this patch from OLK-5.10 to OLK-6.6, LGTM. Tested-by: Yipeng Zou <zouyipeng@huawei.com> Reviewed-by: Yipeng Zou <zouyipeng@huawei.com> 在 2024/4/8 14:26, Jie Zhan 写道:
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9ERMB
------------------------------------------------------------------------
Since commit 4615fbc3788d ("genirq/irqdomain: Don't try to free an interrupt that has no mapping"), we have found failures when re-inserting some specific drivers:
[root@localhost ~]# rmmod hisi_sas_v3_hw [root@localhost ~]# modprobe hisi_sas_v3_hw [ 1295.622525] hisi_sas_v3_hw: probe of 0000:30:04.0 failed with error -2
A relevant discussion can be found at: https://lore.kernel.org/lkml/3d3d0155e66429968cb4f6b4feeae4b3@kernel.org/
This is because IRQs from a low-level domain are not freed together, leaving some leaked. Thus, the next driver insertion fails to allocate the same number of IRQs.
Free a contiguous group of IRQs in one go to fix this issue.
Fixes: 4615fbc3788d ("genirq/irqdomain: Don't try to free an interrupt that has no mapping") Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com> Reviewed-by: Liao Chang <liaochang1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> --- kernel/irq/irqdomain.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 0bdef4fe925b..2ec5bd39635c 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1443,13 +1443,24 @@ static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain, unsigned int nr_irqs) { unsigned int i; + int n;
if (!domain->ops->free) return;
for (i = 0; i < nr_irqs; i++) { - if (irq_domain_get_irq_data(domain, irq_base + i)) - domain->ops->free(domain, irq_base + i, 1); + /* Find the largest possible span of IRQs to free in one go */ + for (n = 0; + ((i + n) < nr_irqs) && + (irq_domain_get_irq_data(domain, irq_base + i + n)); + n++) + ; + + if (!n) + continue; + + domain->ops->free(domain, irq_base + i, n); + i += n; } }
-- Regards, Yipeng Zou
participants (3)
-
Jie Zhan
-
patchwork bot
-
Yipeng Zou