From 6b99c5d21e8245e982c847189897040c55751d17 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sat, 10 May 2025 21:06:20 +0800 Subject: [PATCH] rockchip: backport PCIe MSI fixes for RK356x SoC Backport GIC ITS support for RK356x SoC, which fixes long-standing MSI/MSI-X bug. (Previously MSI-X could only work on one PCIe node) e.g. [ 7.250882] r8125 0002:01:00.0: no MSI/MSI-X. Back to INTx. Tested on Radxa E25 with kmod-r8125-rss driver. Signed-off-by: Chukun Pan Link: https://github.com/openwrt/openwrt/pull/18800 Signed-off-by: Robert Marko --- target/linux/rockchip/armv8/config-6.6 | 1 + ...ts-Share-ITS-tables-with-a-non-trust.patch | 337 ++++++++++++++++++ ...its-Fix-over-allocation-in-itt_alloc.patch | 33 ++ ...-Rockchip-3568002-erratum-workaround.patch | 105 ++++++ ...kchip-rk356x-Add-MSI-controller-node.patch | 51 +++ ...chip-rk356x-Move-PCIe-MSI-to-use-GIC.patch | 28 ++ ...ip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch | 54 +++ 7 files changed, 609 insertions(+) create mode 100644 target/linux/rockchip/patches-6.6/020-v6.13-irqchip-gic-v3-its-Share-ITS-tables-with-a-non-trust.patch create mode 100644 target/linux/rockchip/patches-6.6/021-v6.13-irqchip-gic-v3-its-Fix-over-allocation-in-itt_alloc.patch create mode 100644 target/linux/rockchip/patches-6.6/022-v6.15-irqchip-gic-v3-Add-Rockchip-3568002-erratum-workaround.patch create mode 100644 target/linux/rockchip/patches-6.6/023-01-v6.15-arm64-dts-rockchip-rk356x-Add-MSI-controller-node.patch create mode 100644 target/linux/rockchip/patches-6.6/023-02-v6.15-arm64-dts-rockchip-rk356x-Move-PCIe-MSI-to-use-GIC.patch create mode 100644 target/linux/rockchip/patches-6.6/024-v6.16-arm64-dts-rockchip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch diff --git a/target/linux/rockchip/armv8/config-6.6 b/target/linux/rockchip/armv8/config-6.6 index be5b4b4b5cf..5018b6e2f52 100644 --- a/target/linux/rockchip/armv8/config-6.6 +++ b/target/linux/rockchip/armv8/config-6.6 @@ -563,6 +563,7 @@ CONFIG_RELOCATABLE=y CONFIG_RESET_CONTROLLER=y CONFIG_RESET_SCMI=y CONFIG_RFS_ACCEL=y +CONFIG_ROCKCHIP_ERRATUM_3568002=y CONFIG_ROCKCHIP_ERRATUM_3588001=y CONFIG_ROCKCHIP_GRF=y CONFIG_ROCKCHIP_IODOMAIN=y diff --git a/target/linux/rockchip/patches-6.6/020-v6.13-irqchip-gic-v3-its-Share-ITS-tables-with-a-non-trust.patch b/target/linux/rockchip/patches-6.6/020-v6.13-irqchip-gic-v3-its-Share-ITS-tables-with-a-non-trust.patch new file mode 100644 index 00000000000..92e9bf6c868 --- /dev/null +++ b/target/linux/rockchip/patches-6.6/020-v6.13-irqchip-gic-v3-its-Share-ITS-tables-with-a-non-trust.patch @@ -0,0 +1,337 @@ +From b08e2f42e86b5848add254da45b56fc672e2bced Mon Sep 17 00:00:00 2001 +From: Steven Price +Date: Wed, 2 Oct 2024 15:16:29 +0100 +Subject: [PATCH] irqchip/gic-v3-its: Share ITS tables with a non-trusted + hypervisor + +Within a realm guest the ITS is emulated by the host. This means the +allocations must have been made available to the host by a call to +set_memory_decrypted(). Introduce an allocation function which performs +this extra call. + +For the ITT use a custom genpool-based allocator that calls +set_memory_decrypted() for each page allocated, but then suballocates the +size needed for each ITT. Note that there is no mechanism implemented to +return pages from the genpool, but it is unlikely that the peak number of +devices will be much larger than the normal level - so this isn't expected +to be an issue. + +Co-developed-by: Suzuki K Poulose +Signed-off-by: Suzuki K Poulose +Signed-off-by: Steven Price +Signed-off-by: Thomas Gleixner +Tested-by: Will Deacon +Reviewed-by: Marc Zyngier +Link: https://lore.kernel.org/all/20241002141630.433502-2-steven.price@arm.com +--- + drivers/irqchip/irq-gic-v3-its.c | 138 +++++++++++++++++++++++++------ + 1 file changed, 115 insertions(+), 23 deletions(-) + +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -12,12 +12,14 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -27,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -163,6 +166,7 @@ struct its_device { + struct its_node *its; + struct event_lpi_map event_map; + void *itt; ++ u32 itt_sz; + u32 nr_ites; + u32 device_id; + bool shared; +@@ -198,6 +202,87 @@ static DEFINE_IDA(its_vpeid_ida); + #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) + #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) + ++static struct page *its_alloc_pages_node(int node, gfp_t gfp, ++ unsigned int order) ++{ ++ struct page *page; ++ int ret = 0; ++ ++ page = alloc_pages_node(node, gfp, order); ++ ++ if (!page) ++ return NULL; ++ ++ ret = set_memory_decrypted((unsigned long)page_address(page), ++ 1 << order); ++ /* ++ * If set_memory_decrypted() fails then we don't know what state the ++ * page is in, so we can't free it. Instead we leak it. ++ * set_memory_decrypted() will already have WARNed. ++ */ ++ if (ret) ++ return NULL; ++ ++ return page; ++} ++ ++static struct page *its_alloc_pages(gfp_t gfp, unsigned int order) ++{ ++ return its_alloc_pages_node(NUMA_NO_NODE, gfp, order); ++} ++ ++static void its_free_pages(void *addr, unsigned int order) ++{ ++ /* ++ * If the memory cannot be encrypted again then we must leak the pages. ++ * set_memory_encrypted() will already have WARNed. ++ */ ++ if (set_memory_encrypted((unsigned long)addr, 1 << order)) ++ return; ++ free_pages((unsigned long)addr, order); ++} ++ ++static struct gen_pool *itt_pool; ++ ++static void *itt_alloc_pool(int node, int size) ++{ ++ unsigned long addr; ++ struct page *page; ++ ++ if (size >= PAGE_SIZE) { ++ page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, get_order(size)); ++ ++ return page ? page_address(page) : NULL; ++ } ++ ++ do { ++ addr = gen_pool_alloc(itt_pool, size); ++ if (addr) ++ break; ++ ++ page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 1); ++ if (!page) ++ break; ++ ++ gen_pool_add(itt_pool, (unsigned long)page_address(page), PAGE_SIZE, node); ++ } while (!addr); ++ ++ return (void *)addr; ++} ++ ++static void itt_free_pool(void *addr, int size) ++{ ++ if (!addr) ++ return; ++ ++ if (size >= PAGE_SIZE) { ++ its_free_pages(addr, get_order(size)); ++ return; ++ } ++ ++ gen_pool_free(itt_pool, (unsigned long)addr, size); ++} ++ + /* + * Skip ITSs that have no vLPIs mapped, unless we're on GICv4.1, as we + * always have vSGIs mapped. +@@ -2192,7 +2277,8 @@ static struct page *its_allocate_prop_ta + { + struct page *prop_page; + +- prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ)); ++ prop_page = its_alloc_pages(gfp_flags, ++ get_order(LPI_PROPBASE_SZ)); + if (!prop_page) + return NULL; + +@@ -2203,8 +2289,7 @@ static struct page *its_allocate_prop_ta + + static void its_free_prop_table(struct page *prop_page) + { +- free_pages((unsigned long)page_address(prop_page), +- get_order(LPI_PROPBASE_SZ)); ++ its_free_pages(page_address(prop_page), get_order(LPI_PROPBASE_SZ)); + } + + static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size) +@@ -2326,7 +2411,7 @@ static int its_setup_baser(struct its_no + order = get_order(GITS_BASER_PAGES_MAX * psz); + } + +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order); ++ page = its_alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order); + if (!page) + return -ENOMEM; + +@@ -2339,7 +2424,7 @@ static int its_setup_baser(struct its_no + /* 52bit PA is supported only when PageSize=64K */ + if (psz != SZ_64K) { + pr_err("ITS: no 52bit PA support when psz=%d\n", psz); +- free_pages((unsigned long)base, order); ++ its_free_pages(base, order); + return -ENXIO; + } + +@@ -2395,7 +2480,7 @@ retry_baser: + pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n", + &its->phys_base, its_base_type_string[type], + val, tmp); +- free_pages((unsigned long)base, order); ++ its_free_pages(base, order); + return -ENXIO; + } + +@@ -2534,8 +2619,7 @@ static void its_free_tables(struct its_n + + for (i = 0; i < GITS_BASER_NR_REGS; i++) { + if (its->tables[i].base) { +- free_pages((unsigned long)its->tables[i].base, +- its->tables[i].order); ++ its_free_pages(its->tables[i].base, its->tables[i].order); + its->tables[i].base = NULL; + } + } +@@ -2801,7 +2885,7 @@ static bool allocate_vpe_l2_table(int cp + + /* Allocate memory for 2nd level table */ + if (!table[idx]) { +- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz)); ++ page = its_alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz)); + if (!page) + return false; + +@@ -2920,7 +3004,7 @@ static int allocate_vpe_l1_table(void) + + pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n", + np, npg, psz, epp, esz); +- page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE)); ++ page = its_alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE)); + if (!page) + return -ENOMEM; + +@@ -2966,8 +3050,7 @@ static struct page *its_allocate_pending + { + struct page *pend_page; + +- pend_page = alloc_pages(gfp_flags | __GFP_ZERO, +- get_order(LPI_PENDBASE_SZ)); ++ pend_page = its_alloc_pages(gfp_flags | __GFP_ZERO, get_order(LPI_PENDBASE_SZ)); + if (!pend_page) + return NULL; + +@@ -2979,7 +3062,7 @@ static struct page *its_allocate_pending + + static void its_free_pending_table(struct page *pt) + { +- free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ)); ++ its_free_pages(page_address(pt), get_order(LPI_PENDBASE_SZ)); + } + + /* +@@ -3314,8 +3397,8 @@ static bool its_alloc_table_entry(struct + + /* Allocate memory for 2nd level table */ + if (!table[idx]) { +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, +- get_order(baser->psz)); ++ page = its_alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, ++ get_order(baser->psz)); + if (!page) + return false; + +@@ -3410,7 +3493,6 @@ static struct its_device *its_create_dev + if (WARN_ON(!is_power_of_2(nvecs))) + nvecs = roundup_pow_of_two(nvecs); + +- dev = kzalloc(sizeof(*dev), GFP_KERNEL); + /* + * Even if the device wants a single LPI, the ITT must be + * sized as a power of two (and you need at least one bit...). +@@ -3418,7 +3500,11 @@ static struct its_device *its_create_dev + nr_ites = max(2, nvecs); + sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); + sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; +- itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node); ++ ++ itt = itt_alloc_pool(its->numa_node, sz); ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ + if (alloc_lpis) { + lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); + if (lpi_map) +@@ -3430,9 +3516,9 @@ static struct its_device *its_create_dev + lpi_base = 0; + } + +- if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { ++ if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { + kfree(dev); +- kfree(itt); ++ itt_free_pool(itt, sz); + bitmap_free(lpi_map); + kfree(col_map); + return NULL; +@@ -3442,6 +3528,7 @@ static struct its_device *its_create_dev + + dev->its = its; + dev->itt = itt; ++ dev->itt_sz = sz; + dev->nr_ites = nr_ites; + dev->event_map.lpi_map = lpi_map; + dev->event_map.col_map = col_map; +@@ -3469,7 +3556,7 @@ static void its_free_device(struct its_d + list_del(&its_dev->entry); + raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); + kfree(its_dev->event_map.col_map); +- kfree(its_dev->itt); ++ itt_free_pool(its_dev->itt, its_dev->itt_sz); + kfree(its_dev); + } + +@@ -5112,8 +5199,9 @@ static int __init its_probe_one(struct i + } + } + +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, +- get_order(ITS_CMD_QUEUE_SZ)); ++ page = its_alloc_pages_node(its->numa_node, ++ GFP_KERNEL | __GFP_ZERO, ++ get_order(ITS_CMD_QUEUE_SZ)); + if (!page) { + err = -ENOMEM; + goto out_unmap_sgir; +@@ -5177,7 +5265,7 @@ static int __init its_probe_one(struct i + out_free_tables: + its_free_tables(its); + out_free_cmd: +- free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ)); ++ its_free_pages(its->cmd_base, get_order(ITS_CMD_QUEUE_SZ)); + out_unmap_sgir: + if (its->sgir_base) + iounmap(its->sgir_base); +@@ -5659,6 +5747,10 @@ int __init its_init(struct fwnode_handle + bool has_v4_1 = false; + int err; + ++ itt_pool = gen_pool_create(get_order(ITS_ITT_ALIGN), -1); ++ if (!itt_pool) ++ return -ENOMEM; ++ + gic_rdists = rdists; + + its_parent = parent_domain; diff --git a/target/linux/rockchip/patches-6.6/021-v6.13-irqchip-gic-v3-its-Fix-over-allocation-in-itt_alloc.patch b/target/linux/rockchip/patches-6.6/021-v6.13-irqchip-gic-v3-its-Fix-over-allocation-in-itt_alloc.patch new file mode 100644 index 00000000000..a716cbee7de --- /dev/null +++ b/target/linux/rockchip/patches-6.6/021-v6.13-irqchip-gic-v3-its-Fix-over-allocation-in-itt_alloc.patch @@ -0,0 +1,33 @@ +From bc88d44bd7e45b992cf8c2c2ffbc7bb3e24db4a7 Mon Sep 17 00:00:00 2001 +From: Steven Price +Date: Mon, 21 Oct 2024 11:41:05 +0100 +Subject: [PATCH] irqchip/gic-v3-its: Fix over allocation in + itt_alloc_pool() + +itt_alloc_pool() calls its_alloc_pages_node() to allocate an individual +page to add to the pool (for allocations +Signed-off-by: Steven Price +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/1f6e19c4-1fb9-43ab-a8a2-a465c9cff84b@arm.com +Closes: https://lore.kernel.org/r/ed65312a-245c-4fa5-91ad-5d620cab7c6b%40nvidia.com +--- + drivers/irqchip/irq-gic-v3-its.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -260,7 +260,7 @@ static void *itt_alloc_pool(int node, in + if (addr) + break; + +- page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 1); ++ page = its_alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0); + if (!page) + break; + diff --git a/target/linux/rockchip/patches-6.6/022-v6.15-irqchip-gic-v3-Add-Rockchip-3568002-erratum-workaround.patch b/target/linux/rockchip/patches-6.6/022-v6.15-irqchip-gic-v3-Add-Rockchip-3568002-erratum-workaround.patch new file mode 100644 index 00000000000..9c9e643ff94 --- /dev/null +++ b/target/linux/rockchip/patches-6.6/022-v6.15-irqchip-gic-v3-Add-Rockchip-3568002-erratum-workaround.patch @@ -0,0 +1,105 @@ +From 2d81e1bb625238d40a686ed909ff3e1abab7556a Mon Sep 17 00:00:00 2001 +From: Dmitry Osipenko +Date: Mon, 17 Feb 2025 01:16:32 +0300 +Subject: [PATCH] irqchip/gic-v3: Add Rockchip 3568002 erratum workaround + +Rockchip RK3566/RK3568 GIC600 integration has DDR addressing +limited to the first 32bit of physical address space. Rockchip +assigned Erratum ID #3568002 for this issue. Add driver quirk for +this Rockchip GIC Erratum. + +Note, that the 0x0201743b GIC600 ID is not Rockchip-specific and is +common for many ARM GICv3 implementations. Hence, there is an extra +of_machine_is_compatible() check. + +Signed-off-by: Dmitry Osipenko +Signed-off-by: Thomas Gleixner +Acked-by: Marc Zyngier +Link: https://lore.kernel.org/all/20250216221634.364158-2-dmitry.osipenko@collabora.com +--- + Documentation/arch/arm64/silicon-errata.rst | 2 ++ + arch/arm64/Kconfig | 9 ++++++++ + drivers/irqchip/irq-gic-v3-its.c | 23 ++++++++++++++++++++- + 3 files changed, 33 insertions(+), 1 deletion(-) + +--- a/Documentation/arch/arm64/silicon-errata.rst ++++ b/Documentation/arch/arm64/silicon-errata.rst +@@ -270,6 +270,8 @@ stable kernels. + +----------------+-----------------+-----------------+-----------------------------+ + | Rockchip | RK3588 | #3588001 | ROCKCHIP_ERRATUM_3588001 | + +----------------+-----------------+-----------------+-----------------------------+ ++| Rockchip | RK3568 | #3568002 | ROCKCHIP_ERRATUM_3568002 | +++----------------+-----------------+-----------------+-----------------------------+ + + +----------------+-----------------+-----------------+-----------------------------+ + | Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 | +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1267,6 +1267,15 @@ config NVIDIA_CARMEL_CNP_ERRATUM + + If unsure, say Y. + ++config ROCKCHIP_ERRATUM_3568002 ++ bool "Rockchip 3568002: GIC600 can not access physical addresses higher than 4GB" ++ default y ++ help ++ The Rockchip RK3566 and RK3568 GIC600 SoC integrations have AXI ++ addressing limited to the first 32bit of physical address space. ++ ++ If unsure, say Y. ++ + config ROCKCHIP_ERRATUM_3588001 + bool "Rockchip 3588001: GIC600 can not support shareability attributes" + default y +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -202,13 +202,15 @@ static DEFINE_IDA(its_vpeid_ida); + #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) + #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) + ++static gfp_t gfp_flags_quirk; ++ + static struct page *its_alloc_pages_node(int node, gfp_t gfp, + unsigned int order) + { + struct page *page; + int ret = 0; + +- page = alloc_pages_node(node, gfp, order); ++ page = alloc_pages_node(node, gfp | gfp_flags_quirk, order); + + if (!page) + return NULL; +@@ -4851,6 +4853,17 @@ static bool its_set_non_coherent(void *d + return true; + } + ++static bool __maybe_unused its_enable_rk3568002(void *data) ++{ ++ if (!of_machine_is_compatible("rockchip,rk3566") && ++ !of_machine_is_compatible("rockchip,rk3568")) ++ return false; ++ ++ gfp_flags_quirk |= GFP_DMA32; ++ ++ return true; ++} ++ + static const struct gic_quirk its_quirks[] = { + #ifdef CONFIG_CAVIUM_ERRATUM_22375 + { +@@ -4910,6 +4923,14 @@ static const struct gic_quirk its_quirks + .property = "dma-noncoherent", + .init = its_set_non_coherent, + }, ++#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002 ++ { ++ .desc = "ITS: Rockchip erratum RK3568002", ++ .iidr = 0x0201743b, ++ .mask = 0xffffffff, ++ .init = its_enable_rk3568002, ++ }, ++#endif + { + } + }; diff --git a/target/linux/rockchip/patches-6.6/023-01-v6.15-arm64-dts-rockchip-rk356x-Add-MSI-controller-node.patch b/target/linux/rockchip/patches-6.6/023-01-v6.15-arm64-dts-rockchip-rk356x-Add-MSI-controller-node.patch new file mode 100644 index 00000000000..a31e4595c4d --- /dev/null +++ b/target/linux/rockchip/patches-6.6/023-01-v6.15-arm64-dts-rockchip-rk356x-Add-MSI-controller-node.patch @@ -0,0 +1,51 @@ +From f15be3d4a0a55db2b50f319c378a2d16ceb21f86 Mon Sep 17 00:00:00 2001 +From: Dmitry Osipenko +Date: Mon, 17 Feb 2025 01:16:33 +0300 +Subject: [PATCH] arm64: dts: rockchip: rk356x: Add MSI controller node + +Rockchip 356x SoC's GIC has two hardware integration issues that +affect MSI functionality of the GIC. Previously, both these GIC +issues were worked around by using MBI for MSI instead of ITS +because kernel GIC driver didn't have necessary quirks. + +First issue is about RK356x GIC not supporting programmable +shareability, while reporting it as supported in a GIC's feature +register. Rockchip assigned Erratum ID #3568001 for this issue. This +patch adds dma-noncoherent property to the GIC node, denoting that a SW +workaround is required for mitigating the issue. + +Second issue is about GIC AXI master interface addressing limited to +the first 4GB of physical address space. Rockchip assigned Erratum +ID #3568002 for this issue. + +Now that kernel supports quirks for both of the erratums, add +MSI controller node to RK356x device-tree. + +Signed-off-by: Dmitry Osipenko +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250216221634.364158-3-dmitry.osipenko@collabora.com +--- + arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -364,6 +364,18 @@ + mbi-alias = <0x0 0xfd410000>; + mbi-ranges = <296 24>; + msi-controller; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dma-noncoherent; ++ ++ its: msi-controller@fd440000 { ++ compatible = "arm,gic-v3-its"; ++ reg = <0x0 0xfd440000 0 0x20000>; ++ dma-noncoherent; ++ msi-controller; ++ #msi-cells = <1>; ++ }; + }; + + usb_host0_ehci: usb@fd800000 { diff --git a/target/linux/rockchip/patches-6.6/023-02-v6.15-arm64-dts-rockchip-rk356x-Move-PCIe-MSI-to-use-GIC.patch b/target/linux/rockchip/patches-6.6/023-02-v6.15-arm64-dts-rockchip-rk356x-Move-PCIe-MSI-to-use-GIC.patch new file mode 100644 index 00000000000..d1281332b45 --- /dev/null +++ b/target/linux/rockchip/patches-6.6/023-02-v6.15-arm64-dts-rockchip-rk356x-Move-PCIe-MSI-to-use-GIC.patch @@ -0,0 +1,28 @@ +From b956c9de91757c9478e24fc9f6a57fd46f0a49f0 Mon Sep 17 00:00:00 2001 +From: Dmitry Osipenko +Date: Mon, 17 Feb 2025 01:16:34 +0300 +Subject: [PATCH] arm64: dts: rockchip: rk356x: Move PCIe MSI to use GIC + ITS instead of MBI + +Rockchip 356x device-tree now supports GIC ITS. Move PCIe controller's +MSI to use ITS instead of MBI. This removes extra CPU overhead of handling +PCIe MBIs by letting GIC's ITS to serve the PCIe MSIs. + +Signed-off-by: Dmitry Osipenko +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250216221634.364158-4-dmitry.osipenko@collabora.com +--- + arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -1043,7 +1043,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <2>; +- msi-map = <0x0 &gic 0x0 0x1000>; ++ msi-map = <0x0 &its 0x0 0x1000>; + num-lanes = <1>; + phys = <&combphy2 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; diff --git a/target/linux/rockchip/patches-6.6/024-v6.16-arm64-dts-rockchip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch b/target/linux/rockchip/patches-6.6/024-v6.16-arm64-dts-rockchip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch new file mode 100644 index 00000000000..c5bbaed492f --- /dev/null +++ b/target/linux/rockchip/patches-6.6/024-v6.16-arm64-dts-rockchip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch @@ -0,0 +1,54 @@ +From fbea35a661ed100cee2f3bab8015fb0155508106 Mon Sep 17 00:00:00 2001 +From: Chukun Pan +Date: Sat, 8 Mar 2025 17:30:08 +0800 +Subject: [PATCH] arm64: dts: rockchip: Move rk3568 PCIe3 MSI to use GIC ITS + +Following commit b956c9de9175 ("arm64: dts: rockchip: rk356x: Move +PCIe MSI to use GIC ITS instead of MBI"), change the PCIe3 controller's +MSI on rk3568 to use ITS, so that all MSI-X can work properly. + +Signed-off-by: Chukun Pan +Link: https://lore.kernel.org/r/20250308093008.568437-2-amadeus@jmu.edu.cn +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -64,7 +64,7 @@ + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x10 0x1f>; + clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, + <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, + <&cru CLK_PCIE30X1_AUX_NDFT>; +@@ -87,7 +87,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; +- msi-map = <0x0 &gic 0x1000 0x1000>; ++ msi-map = <0x1000 &its 0x1000 0x1000>; + num-lanes = <1>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; +@@ -117,7 +117,7 @@ + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x20 0x2f>; + clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, + <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, + <&cru CLK_PCIE30X2_AUX_NDFT>; +@@ -140,7 +140,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; +- msi-map = <0x0 &gic 0x2000 0x1000>; ++ msi-map = <0x2000 &its 0x2000 0x1000>; + num-lanes = <2>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; -- 2.47.2