[openwrt/openwrt] rockchip: backport PCIe MSI fixes for RK356x SoC
LEDE Commits
lede-commits at lists.infradead.org
Sat May 17 02:30:26 PDT 2025
robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/6b99c5d21e8245e982c847189897040c55751d17
commit 6b99c5d21e8245e982c847189897040c55751d17
Author: Chukun Pan <amadeus at jmu.edu.cn>
AuthorDate: Sat May 10 21:06:20 2025 +0800
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 <amadeus at jmu.edu.cn>
Link: https://github.com/openwrt/openwrt/pull/18800
Signed-off-by: Robert Marko <robimarko at gmail.com>
---
target/linux/rockchip/armv8/config-6.6 | 1 +
...-v3-its-Share-ITS-tables-with-a-non-trust.patch | 337 +++++++++++++++++++++
...c-v3-its-Fix-over-allocation-in-itt_alloc.patch | 33 ++
...3-Add-Rockchip-3568002-erratum-workaround.patch | 105 +++++++
...s-rockchip-rk356x-Add-MSI-controller-node.patch | 51 ++++
...-rockchip-rk356x-Move-PCIe-MSI-to-use-GIC.patch | 28 ++
...ockchip-Move-rk3568-PCIe3-MSI-to-use-GIC-.patch | 54 ++++
7 files changed, 609 insertions(+)
diff --git a/target/linux/rockchip/armv8/config-6.6 b/target/linux/rockchip/armv8/config-6.6
index be5b4b4b5c..5018b6e2f5 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 0000000000..92e9bf6c86
--- /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 <steven.price at arm.com>
+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 <suzuki.poulose at arm.com>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
+Signed-off-by: Steven Price <steven.price at arm.com>
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+Tested-by: Will Deacon <will at kernel.org>
+Reviewed-by: Marc Zyngier <maz at kernel.org>
+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 <linux/crash_dump.h>
+ #include <linux/delay.h>
+ #include <linux/efi.h>
++#include <linux/genalloc.h>
+ #include <linux/interrupt.h>
+ #include <linux/iommu.h>
+ #include <linux/iopoll.h>
+ #include <linux/irqdomain.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
++#include <linux/mem_encrypt.h>
+ #include <linux/memblock.h>
+ #include <linux/mm.h>
+ #include <linux/msi.h>
+@@ -27,6 +29,7 @@
+ #include <linux/of_pci.h>
+ #include <linux/of_platform.h>
+ #include <linux/percpu.h>
++#include <linux/set_memory.h>
+ #include <linux/slab.h>
+ #include <linux/syscore_ops.h>
+
+@@ -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 0000000000..a716cbee7d
--- /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 <steven.price at arm.com>
+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 <PAGE_SIZE). However the final
+argument of its_alloc_pages_node() is the page order not the number of
+pages. Currently it allocates two pages and leaks the second page.
+Fix it by passing 0 instead (1 << 0 = 1 page).
+
+Fixes: b08e2f42e86b ("irqchip/gic-v3-its: Share ITS tables with a non-trusted hypervisor")
+Reported-by: Shanker Donthineni <sdonthineni at nvidia.com>
+Signed-off-by: Steven Price <steven.price at arm.com>
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+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 0000000000..9c9e643ff9
--- /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 <dmitry.osipenko at collabora.com>
+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 <dmitry.osipenko at collabora.com>
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+Acked-by: Marc Zyngier <maz at kernel.org>
+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 0000000000..a31e4595c4
--- /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 <dmitry.osipenko at collabora.com>
+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 <dmitry.osipenko at collabora.com>
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+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 at fd440000 {
++ compatible = "arm,gic-v3-its";
++ reg = <0x0 0xfd440000 0 0x20000>;
++ dma-noncoherent;
++ msi-controller;
++ #msi-cells = <1>;
++ };
+ };
+
+ usb_host0_ehci: usb at 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 0000000000..d1281332b4
--- /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 <dmitry.osipenko at collabora.com>
+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 <dmitry.osipenko at collabora.com>
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+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 0000000000..c5bbaed492
--- /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 <amadeus at jmu.edu.cn>
+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 <amadeus at jmu.edu.cn>
+Link: https://lore.kernel.org/r/20250308093008.568437-2-amadeus@jmu.edu.cn
+Signed-off-by: Heiko Stuebner <heiko at sntech.de>
+---
+ 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";
More information about the lede-commits
mailing list