In dual-bridges scenario, some bugs were found for irq controllers drivers, so the patch serie is used to fix them.
V1->V2: 1. Remove all of ChangeID in patches 2. Exchange the sequence of some patches 3. Adjust code style of if...else... in patch[2]
Jianmin Lv (5): irqchip/loongson-eiointc: Fix returned value on parsing MADT irqchip/loongson-eiointc: Fix incorrect use of acpi_get_vec_parent irqchip/loongson-eiointc: Fix registration of syscore_ops irqchip/loongson-pch-pic: Fix registration of syscore_ops irqchip/loongson-pch-pic: Fix pch_pic_acpi_init calling
drivers/irqchip/irq-loongson-eiointc.c | 32 ++++++++++++++++++-------- drivers/irqchip/irq-loongson-pch-pic.c | 6 ++++- 2 files changed, 27 insertions(+), 11 deletions(-)
In pch_pic_parse_madt(), a NULL parent pointer will be returned from acpi_get_vec_parent() for second pch-pic domain related to second bridge while calling eiointc_acpi_init() at first time, where the parent of it has not been initialized yet, and will be initialized during second time calling eiointc_acpi_init(). So, it's reasonable to return zero so that failure of acpi_table_parse_madt() will be avoided, or else acpi_cascade_irqdomain_init() will return and initialization of followed pch_msi domain will be skipped.
Although it does not matter when pch_msi_parse_madt() returns -EINVAL if no invalid parent is found, it's also reasonable to return zero for that.
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index d15fd38c1756..62a632d73991 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -343,7 +343,7 @@ static int __init pch_pic_parse_madt(union acpi_subtable_headers *header, if (parent) return pch_pic_acpi_init(parent, pchpic_entry);
- return -EINVAL; + return 0; }
static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, @@ -355,7 +355,7 @@ static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, if (parent) return pch_msi_acpi_init(parent, pchmsi_entry);
- return -EINVAL; + return 0; }
static int __init acpi_cascade_irqdomain_init(void)
On Fri, Mar 31, 2023 at 07:38:56PM +0800, Jianmin Lv wrote:
In pch_pic_parse_madt(), a NULL parent pointer will be returned from acpi_get_vec_parent() for second pch-pic domain related to second bridge while calling eiointc_acpi_init() at first time, where the parent of it has not been initialized yet, and will be initialized during second time calling eiointc_acpi_init(). So, it's reasonable to return zero so that failure of acpi_table_parse_madt() will be avoided, or else acpi_cascade_irqdomain_init() will return and initialization of followed pch_msi domain will be skipped.
Although it does not matter when pch_msi_parse_madt() returns -EINVAL if no invalid parent is found, it's also reasonable to return zero for that.
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn
drivers/irqchip/irq-loongson-eiointc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
Ok, thanks, got it.
On 2023/3/31 下午9:17, Greg KH wrote:
On Fri, Mar 31, 2023 at 07:38:56PM +0800, Jianmin Lv wrote:
In pch_pic_parse_madt(), a NULL parent pointer will be returned from acpi_get_vec_parent() for second pch-pic domain related to second bridge while calling eiointc_acpi_init() at first time, where the parent of it has not been initialized yet, and will be initialized during second time calling eiointc_acpi_init(). So, it's reasonable to return zero so that failure of acpi_table_parse_madt() will be avoided, or else acpi_cascade_irqdomain_init() will return and initialization of followed pch_msi domain will be skipped.
Although it does not matter when pch_msi_parse_madt() returns -EINVAL if no invalid parent is found, it's also reasonable to return zero for that.
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn
drivers/irqchip/irq-loongson-eiointc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
In eiointc_acpi_init(), a *eiointc* node is passed into acpi_get_vec_parent() instead of a required *NUMA* node (on some chip like 3C5000L, a *NUMA* node means a *eiointc* node, but on some chip like 3C5000, a *NUMA* node contains 4 *eiointc* nodes), and node in struct acpi_vector_group is essentially a *NUMA* node, which will lead to no parent matched for passed *eiointc* node. so the patch adjusts code to use *NUMA* node for parameter node of acpi_set_vec_parent/acpi_get_vec_parent.
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 62a632d73991..d16ed64feb3d 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -280,9 +280,6 @@ static void acpi_set_vec_parent(int node, struct irq_domain *parent, struct acpi { int i;
- if (cpu_has_flatmode) - node = cpu_to_node(node * CORES_PER_EIO_NODE); - for (i = 0; i < MAX_IO_PICS; i++) { if (node == vec_group[i].node) { vec_group[i].parent = parent; @@ -349,8 +346,16 @@ static int __init pch_pic_parse_madt(union acpi_subtable_headers *header, static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, const unsigned long end) { + struct irq_domain *parent; struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header; - struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group); + int node; + + if (cpu_has_flatmode) + node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE); + else + node = eiointc_priv[nr_pics - 1]->node; + + parent = acpi_get_vec_parent(node, msi_group);
if (parent) return pch_msi_acpi_init(parent, pchmsi_entry); @@ -379,6 +384,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent, int i, ret, parent_irq; unsigned long node_map; struct eiointc_priv *priv; + int node;
priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -421,8 +427,12 @@ int __init eiointc_acpi_init(struct irq_domain *parent, "irqchip/loongarch/intc:starting", eiointc_router_init, NULL);
- acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); - acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); + if (cpu_has_flatmode) + node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); + else + node = acpi_eiointc->node; + acpi_set_vec_parent(node, priv->eiointc_domain, pch_group); + acpi_set_vec_parent(node, priv->eiointc_domain, msi_group); ret = acpi_cascade_irqdomain_init();
return ret;
When support suspend/resume for loongson-eiointc, the syscore_ops is registered twice in dual-bridges machines where there are two eiointc IRQ domains. Repeated registration of an same syscore_ops broke syscore_ops_list. Also, cpuhp_setup_state_nocalls is only needed to call for once. So the patch will corret them.
Fixes: a90335c2dfb4 ("irqchip/loongson-eiointc: Add suspend/resume support")
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index d16ed64feb3d..90181c42840b 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -422,10 +422,12 @@ int __init eiointc_acpi_init(struct irq_domain *parent, parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
- register_syscore_ops(&eiointc_syscore_ops); - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, + if (nr_pics == 1) { + register_syscore_ops(&eiointc_syscore_ops); + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, "irqchip/loongarch/intc:starting", eiointc_router_init, NULL); + }
if (cpu_has_flatmode) node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
Hi,
Thanks for your patch.
FYI: kernel test robot notices the stable kernel rule is not satisfied.
Rule: 'Cc: stable@vger.kernel.org' or 'commit <sha1> upstream.' Subject: [PATCH V2 3/5] irqchip/loongson-eiointc: Fix registration of syscore_ops Link: https://lore.kernel.org/stable/20230331113900.9105-4-lvjianmin%40loongson.cn
The check is based on https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
When support suspend/resume for loongson-pch-pic, the syscore_ops is registered twice in dual-bridges machines where there are two pch-pic IRQ domains. Repeated registration of an same syscore_ops broke syscore_ops_list, so the patch will corret it.
Fixes: 1ed008a2c331 ("irqchip/loongson-pch-pic: Add suspend/resume support") Signed-off-by: Jianmin Lv lvjianmin@loongson.cn --- drivers/irqchip/irq-loongson-pch-pic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index 437f1af693d0..64fa67d4ee7a 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -311,7 +311,8 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base, pch_pic_handle[nr_pics] = domain_handle; pch_pic_priv[nr_pics++] = priv;
- register_syscore_ops(&pch_pic_syscore_ops); + if (nr_pics == 1) + register_syscore_ops(&pch_pic_syscore_ops);
return 0;
For dual-bridges scenario, pch_pic_acpi_init() will be called in following path:
cpuintc_acpi_init acpi_cascade_irqdomain_init(in cpuintc driver) acpi_table_parse_madt eiointc_parse_madt eiointc_acpi_init /* this will be called two times correspondingto parsing two eiointc entries in MADT under dual-bridges scenario*/ acpi_cascade_irqdomain_init(in eiointc driver) acpi_table_parse_madt pch_pic_parse_madt pch_pic_acpi_init /* this will be called depend on valid parent IRQ domain handle for one or two times corresponding to parsing two pchpic entries in MADT druring calling eiointc_acpi_init() under dual-bridges scenario*/
During the first eiointc_acpi_init() calling, the pch_pic_acpi_init() will be called just one time since only one valid parent IRQ domain handle will be found for current eiointc IRQ domain.
During the second eiointc_acpi_init() calling, the pch_pic_acpi_init() will be called two times since two valid parent IRQ domain handles will be found. So in pch_pic_acpi_init(), we must have a reasonable way to prevent from creating second same pch_pic IRQ domain.
The patch matches gsi base information in created pch_pic IRQ domains to check if the target domain has been created to avoid the bug mentioned above.
Signed-off-by: Jianmin Lv lvjianmin@loongson.cn --- drivers/irqchip/irq-loongson-pch-pic.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index 64fa67d4ee7a..e5fe4d50be05 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -404,6 +404,9 @@ int __init pch_pic_acpi_init(struct irq_domain *parent, int ret, vec_base; struct fwnode_handle *domain_handle;
+ if (find_pch_pic(acpi_pchpic->gsi_base) >= 0) + return 0; + vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ;
domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address);
linux-stable-mirror@lists.linaro.org