From 12aaf67584cf19dc84615b7aba272fe642c35b8b Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 21 Nov 2024 12:48:25 +0000 Subject: [PATCH 1/3] irqchip/irq-mvebu-sei: Move misplaced select() callback to SEI CP domain Commit fbdf14e90ce4 ("irqchip/irq-mvebu-sei: Switch to MSI parent") introduced in v6.11-rc1 broke Mavell Armada platforms (and possibly others) by incorrectly switching irq-mvebu-sei to MSI parent. In the above commit, msi_parent_ops is set for the sei->cp_domain, but rather than adding a .select method to mvebu_sei_cp_domain_ops (which is associated with sei->cp_domain), it was added to mvebu_sei_domain_ops which is associated with sei->sei_domain, which doesn't have any msi_parent_ops. This makes the call to msi_lib_irq_domain_select() always fail. This bug manifests itself with the following kernel messages on Armada 8040 based systems: platform f21e0000.interrupt-controller:interrupt-controller@50: deferred probe pending: (reason unknown) platform f41e0000.interrupt-controller:interrupt-controller@50: deferred probe pending: (reason unknown) Move the select callback to mvebu_sei_cp_domain_ops to cure it. Fixes: fbdf14e90ce4 ("irqchip/irq-mvebu-sei: Switch to MSI parent") Signed-off-by: Russell King (Oracle) Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/E1tE6bh-004CmX-QU@rmk-PC.armlinux.org.uk --- drivers/irqchip/irq-mvebu-sei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c index f8c70f2d100a1..065166ab5dbc0 100644 --- a/drivers/irqchip/irq-mvebu-sei.c +++ b/drivers/irqchip/irq-mvebu-sei.c @@ -192,7 +192,6 @@ static void mvebu_sei_domain_free(struct irq_domain *domain, unsigned int virq, } static const struct irq_domain_ops mvebu_sei_domain_ops = { - .select = msi_lib_irq_domain_select, .alloc = mvebu_sei_domain_alloc, .free = mvebu_sei_domain_free, }; @@ -306,6 +305,7 @@ static void mvebu_sei_cp_domain_free(struct irq_domain *domain, } static const struct irq_domain_ops mvebu_sei_cp_domain_ops = { + .select = msi_lib_irq_domain_select, .alloc = mvebu_sei_cp_domain_alloc, .free = mvebu_sei_cp_domain_free, }; From f82e62d470cc990ebd9d691f931dd418e4e9cea9 Mon Sep 17 00:00:00 2001 From: Zhou Wang Date: Sat, 16 Nov 2024 16:01:26 +0800 Subject: [PATCH 2/3] irqchip/gicv3-its: Add workaround for hip09 ITS erratum 162100801 When enabling GICv4.1 in hip09, VMAPP fails to clear some caches during the unmap operation, which can causes vSGIs to be lost. To fix the issue, invalidate the related vPE cache through GICR_INVALLR after VMOVP. Suggested-by: Marc Zyngier Co-developed-by: Nianyao Tang Signed-off-by: Nianyao Tang Signed-off-by: Zhou Wang Signed-off-by: Thomas Gleixner Reviewed-by: Marc Zyngier --- Documentation/arch/arm64/silicon-errata.rst | 2 + arch/arm64/Kconfig | 11 +++++ drivers/irqchip/irq-gic-v3-its.c | 50 ++++++++++++++++----- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index 65bfab1b18614..77db10e944f03 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -258,6 +258,8 @@ stable kernels. | Hisilicon | Hip{08,09,10,10C| #162001900 | N/A | | | ,11} SMMU PMCG | | | +----------------+-----------------+-----------------+-----------------------------+ +| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 | ++----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | +----------------+-----------------+-----------------+-----------------------------+ diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index d743737bf9ce9..ea39e3daf2245 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1236,6 +1236,17 @@ config HISILICON_ERRATUM_161600802 If unsure, say Y. +config HISILICON_ERRATUM_162100801 + bool "Hip09 162100801 erratum support" + default y + help + When enabling GICv4.1 in hip09, VMAPP will fail to clear some caches + during unmapping operation, which will cause some vSGIs lost. + To fix the issue, invalidate related vPE cache through GICR_INVALLR + after VMOVP. + + If unsure, say Y. + config QCOM_FALKOR_ERRATUM_1003 bool "Falkor E1003: Incorrect translation due to ASID change" default y diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 16acce0f102d4..92244cfa04647 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -47,6 +47,7 @@ #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) #define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3) +#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4) #define RD_LOCAL_LPI_ENABLED BIT(0) #define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1) @@ -64,6 +65,7 @@ static u32 lpi_id_bits; #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) static u8 __ro_after_init lpi_prop_prio; +static struct its_node *find_4_1_its(void); /* * Collection structure - just an ID, and a redistributor address to @@ -3883,6 +3885,20 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to) raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags); } +static void its_vpe_4_1_invall_locked(int cpu, struct its_vpe *vpe) +{ + void __iomem *rdbase; + u64 val; + + val = GICR_INVALLR_V; + val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id); + + guard(raw_spinlock)(&gic_data_rdist_cpu(cpu)->rd_lock); + rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base; + gic_write_lpir(val, rdbase + GICR_INVALLR); + wait_for_syncr(rdbase); +} + static int its_vpe_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) @@ -3890,6 +3906,7 @@ static int its_vpe_set_affinity(struct irq_data *d, struct its_vpe *vpe = irq_data_get_irq_chip_data(d); unsigned int from, cpu = nr_cpu_ids; struct cpumask *table_mask; + struct its_node *its; unsigned long flags; /* @@ -3952,6 +3969,11 @@ static int its_vpe_set_affinity(struct irq_data *d, vpe->col_idx = cpu; its_send_vmovp(vpe); + + its = find_4_1_its(); + if (its && its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100801) + its_vpe_4_1_invall_locked(cpu, vpe); + its_vpe_db_proxy_move(vpe, from, cpu); out: @@ -4259,22 +4281,12 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, static void its_vpe_4_1_invall(struct its_vpe *vpe) { - void __iomem *rdbase; unsigned long flags; - u64 val; int cpu; - val = GICR_INVALLR_V; - val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id); - /* Target the redistributor this vPE is currently known on */ cpu = vpe_to_cpuid_lock(vpe, &flags); - raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock); - rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base; - gic_write_lpir(val, rdbase + GICR_INVALLR); - - wait_for_syncr(rdbase); - raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock); + its_vpe_4_1_invall_locked(cpu, vpe); vpe_to_cpuid_unlock(vpe, flags); } @@ -4867,6 +4879,14 @@ static bool its_set_non_coherent(void *data) return true; } +static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data) +{ + struct its_node *its = data; + + its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801; + return true; +} + static const struct gic_quirk its_quirks[] = { #ifdef CONFIG_CAVIUM_ERRATUM_22375 { @@ -4913,6 +4933,14 @@ static const struct gic_quirk its_quirks[] = { .init = its_enable_quirk_hip07_161600802, }, #endif +#ifdef CONFIG_HISILICON_ERRATUM_162100801 + { + .desc = "ITS: Hip09 erratum 162100801", + .iidr = 0x00051736, + .mask = 0xffffffff, + .init = its_enable_quirk_hip09_162100801, + }, +#endif #ifdef CONFIG_ROCKCHIP_ERRATUM_3588001 { .desc = "ITS: Rockchip erratum RK3588001", From cc47268cb4841c84d54f0ac73858986bcd515eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 9 Nov 2024 18:38:27 +0100 Subject: [PATCH 3/3] irqchip: Switch back to struct platform_driver::remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 0edb555a65d1 ("platform: Make platform_driver::remove() return void") .remove() is (again) the right callback to implement for platform drivers. Convert all platform drivers below drivers/irqchip/ to use .remove(), with the eventual goal to drop struct platform_driver::remove_new(). As .remove() and .remove_new() have the same prototypes, conversion is done by just changing the structure member name in the driver initializer. Signed-off-by: Uwe Kleine-König Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20241109173828.291172-2-u.kleine-koenig@baylibre.com --- drivers/irqchip/irq-imgpdc.c | 2 +- drivers/irqchip/irq-imx-intmux.c | 2 +- drivers/irqchip/irq-imx-irqsteer.c | 2 +- drivers/irqchip/irq-keystone.c | 2 +- drivers/irqchip/irq-ls-scfg-msi.c | 2 +- drivers/irqchip/irq-madera.c | 2 +- drivers/irqchip/irq-mvebu-pic.c | 2 +- drivers/irqchip/irq-pruss-intc.c | 2 +- drivers/irqchip/irq-renesas-intc-irqpin.c | 2 +- drivers/irqchip/irq-renesas-irqc.c | 2 +- drivers/irqchip/irq-renesas-rza1.c | 2 +- drivers/irqchip/irq-ts4800.c | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c index b42ed68acfa66..85f80bac09615 100644 --- a/drivers/irqchip/irq-imgpdc.c +++ b/drivers/irqchip/irq-imgpdc.c @@ -479,7 +479,7 @@ static struct platform_driver pdc_intc_driver = { .of_match_table = pdc_intc_match, }, .probe = pdc_intc_probe, - .remove_new = pdc_intc_remove, + .remove = pdc_intc_remove, }; static int __init pdc_intc_init(void) diff --git a/drivers/irqchip/irq-imx-intmux.c b/drivers/irqchip/irq-imx-intmux.c index 511adfaeec822..787543d07565b 100644 --- a/drivers/irqchip/irq-imx-intmux.c +++ b/drivers/irqchip/irq-imx-intmux.c @@ -361,6 +361,6 @@ static struct platform_driver imx_intmux_driver = { .pm = &imx_intmux_pm_ops, }, .probe = imx_intmux_probe, - .remove_new = imx_intmux_remove, + .remove = imx_intmux_remove, }; builtin_platform_driver(imx_intmux_driver); diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c index 75a0e980ff352..b0e9788c00454 100644 --- a/drivers/irqchip/irq-imx-irqsteer.c +++ b/drivers/irqchip/irq-imx-irqsteer.c @@ -328,6 +328,6 @@ static struct platform_driver imx_irqsteer_driver = { .pm = &imx_irqsteer_pm_ops, }, .probe = imx_irqsteer_probe, - .remove_new = imx_irqsteer_remove, + .remove = imx_irqsteer_remove, }; builtin_platform_driver(imx_irqsteer_driver); diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c index 30f1979fa1240..808c781e25483 100644 --- a/drivers/irqchip/irq-keystone.c +++ b/drivers/irqchip/irq-keystone.c @@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(of, keystone_irq_dt_ids); static struct platform_driver keystone_irq_device_driver = { .probe = keystone_irq_probe, - .remove_new = keystone_irq_remove, + .remove = keystone_irq_remove, .driver = { .name = "keystone_irq", .of_match_table = of_match_ptr(keystone_irq_dt_ids), diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 1aef5c4d27c63..c0e1aafe468c3 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c @@ -418,7 +418,7 @@ static struct platform_driver ls_scfg_msi_driver = { .of_match_table = ls_scfg_msi_id, }, .probe = ls_scfg_msi_probe, - .remove_new = ls_scfg_msi_remove, + .remove = ls_scfg_msi_remove, }; module_platform_driver(ls_scfg_msi_driver); diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c index acceb6e7fa95f..b32982c11515f 100644 --- a/drivers/irqchip/irq-madera.c +++ b/drivers/irqchip/irq-madera.c @@ -236,7 +236,7 @@ static void madera_irq_remove(struct platform_device *pdev) static struct platform_driver madera_irq_driver = { .probe = madera_irq_probe, - .remove_new = madera_irq_remove, + .remove = madera_irq_remove, .driver = { .name = "madera-irq", .pm = &madera_irq_pm_ops, diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c index 08b0cc862adf0..bd1e06e05a396 100644 --- a/drivers/irqchip/irq-mvebu-pic.c +++ b/drivers/irqchip/irq-mvebu-pic.c @@ -183,7 +183,7 @@ MODULE_DEVICE_TABLE(of, mvebu_pic_of_match); static struct platform_driver mvebu_pic_driver = { .probe = mvebu_pic_probe, - .remove_new = mvebu_pic_remove, + .remove = mvebu_pic_remove, .driver = { .name = "mvebu-pic", .of_match_table = mvebu_pic_of_match, diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c index 060eb000e9d35..bee01980b4630 100644 --- a/drivers/irqchip/irq-pruss-intc.c +++ b/drivers/irqchip/irq-pruss-intc.c @@ -648,7 +648,7 @@ static struct platform_driver pruss_intc_driver = { .suppress_bind_attrs = true, }, .probe = pruss_intc_probe, - .remove_new = pruss_intc_remove, + .remove = pruss_intc_remove, }; module_platform_driver(pruss_intc_driver); diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 9ad37237ba954..954419f2460d1 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -584,7 +584,7 @@ static SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL); static struct platform_driver intc_irqpin_device_driver = { .probe = intc_irqpin_probe, - .remove_new = intc_irqpin_remove, + .remove = intc_irqpin_remove, .driver = { .name = "renesas_intc_irqpin", .of_match_table = intc_irqpin_dt_ids, diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c index 76026e0b8e201..cbce8ffc7de4a 100644 --- a/drivers/irqchip/irq-renesas-irqc.c +++ b/drivers/irqchip/irq-renesas-irqc.c @@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, irqc_dt_ids); static struct platform_driver irqc_device_driver = { .probe = irqc_probe, - .remove_new = irqc_remove, + .remove = irqc_remove, .driver = { .name = "renesas_irqc", .of_match_table = irqc_dt_ids, diff --git a/drivers/irqchip/irq-renesas-rza1.c b/drivers/irqchip/irq-renesas-rza1.c index f05afe82db4d1..d4e6a68889ec1 100644 --- a/drivers/irqchip/irq-renesas-rza1.c +++ b/drivers/irqchip/irq-renesas-rza1.c @@ -259,7 +259,7 @@ MODULE_DEVICE_TABLE(of, rza1_irqc_dt_ids); static struct platform_driver rza1_irqc_device_driver = { .probe = rza1_irqc_probe, - .remove_new = rza1_irqc_remove, + .remove = rza1_irqc_remove, .driver = { .name = "renesas_rza1_irqc", .of_match_table = rza1_irqc_dt_ids, diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c index b5dddb3c1568e..cc219f28d317f 100644 --- a/drivers/irqchip/irq-ts4800.c +++ b/drivers/irqchip/irq-ts4800.c @@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(of, ts4800_ic_of_match); static struct platform_driver ts4800_ic_driver = { .probe = ts4800_ic_probe, - .remove_new = ts4800_ic_remove, + .remove = ts4800_ic_remove, .driver = { .name = "ts4800-irqc", .of_match_table = ts4800_ic_of_match,