arm-bsp/tc: CI-700 driver enablement in kernel.

Message ID 20220428154734.442847-1-rupinderjit.singh@arm.com
State New
Headers show
Series arm-bsp/tc: CI-700 driver enablement in kernel. | expand

Commit Message

Rupinderjit Singh April 28, 2022, 3:47 p.m. UTC
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
Change-Id: If30b32a0f8ec9dbfe8bbf527eeb909a4c2540e9b
---
 .../0002-Enable-CI-700-interconnect.patch     |  34 ++
 .../trusted-firmware-a-tc.inc                 |   1 +
 .../bsp/arm-platforms/tc.scc                  |   1 +
 .../bsp/arm-platforms/tc/ci700.cfg            |   1 +
 .../linux/linux-arm-platforms.inc             |  14 +
 ...24-perf-arm-cmn-Use-irq_set_affinity.patch |  74 +++
 ...m-cmn-Fix-CPU-hotplug-unregistration.patch |  46 ++
 ...rf-arm-cmn-Account-for-NUMA-affinity.patch | 107 ++++
 ...rm-cmn-Drop-compile-test-restriction.patch |  89 +++
 ...rf-arm-cmn-Refactor-node-ID-handling.patch | 155 +++++
 ...rf-arm-cmn-Streamline-node-iteration.patch | 118 ++++
 ...drivers-perf-arm-cmn-Add-space-after.patch |  34 ++
 ...1-perf-arm-cmn-Refactor-DTM-handling.patch | 406 +++++++++++++
 ...f-arm-cmn-Optimise-DTM-counter-reads.patch |  56 ++
 ...rm-cmn-Optimise-DTC-counter-accesses.patch | 111 ++++
 ...Move-group-validation-data-off-stack.patch | 108 ++++
 ...-arm-cmn-Demarcate-CMN-600-specifics.patch | 466 +++++++++++++++
 ...perf-arm-cmn-Support-new-IP-features.patch | 549 ++++++++++++++++++
 ...0037-perf-arm-cmn-Add-CI-700-Support.patch | 150 +++++
 tatus                                         | 168 ++++++
 20 files changed, 2688 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/0002-Enable-CI-700-interconnect.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
 create mode 100644 tatus

Patch

diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/0002-Enable-CI-700-interconnect.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/0002-Enable-CI-700-interconnect.patch
new file mode 100644
index 0000000..2add0af
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/0002-Enable-CI-700-interconnect.patch
@@ -0,0 +1,34 @@ 
+From 366215a3705228a12efe9f92f1d1033f34ee89fa Mon Sep 17 00:00:00 2001
+From: Rupinderjit Singh <rupinderjit.singh@arm.com>
+Date: Thu, 21 Apr 2022 14:45:23 +0100
+Subject: [PATCH] Enable CI-700 interconnect
+
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+Change-Id: Ie56d47a0b65274a467e98b9ecd3caf25dfe10544
+
+Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/14918]
+
+---
+ fdts/tc.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/fdts/tc.dts b/fdts/tc.dts
+index 7c0e84260..d0985851d 100644
+--- a/fdts/tc.dts
++++ b/fdts/tc.dts
+@@ -461,6 +461,12 @@
+ 		status = "okay";
+ 	};
+ 
++        cmn-pmu {
++                compatible = "arm,ci-700";
++                reg = <0x0 0x50000000 0x0 0x10000000>;
++                interrupts = <0x0 460 0x4>;
++        };
++
+ 	dp0: display@2cc00000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc
index 4d14b95..a54ccbd 100644
--- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc.inc
@@ -8,6 +8,7 @@  DEPENDS += "scp-firmware util-linux-native gptfdisk-native"
 
 SRC_URI:append = " \
     file://0001-plat-tc-Increase-maximum-BL2-size.patch \
+    file://0002-Enable-CI-700-interconnect.patch \
     file://generate_metadata.py \
     "
 
diff --git a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc
index 86e450c..c1dffe7 100644
--- a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc
+++ b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc.scc
@@ -5,3 +5,4 @@  kconf non-hardware tc/gralloc.cfg
 kconf non-hardware tc/mali.cfg
 kconf non-hardware tc/tee.cfg
 kconf non-hardware tc/virtio.cfg
+kconf non-hardware tc/ci700.cfg
diff --git a/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg
new file mode 100644
index 0000000..50c0153
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/arm-platforms-kmeta/bsp/arm-platforms/tc/ci700.cfg
@@ -0,0 +1 @@ 
+CONFIG_ARM_CMN=y
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
index 95715c6..fc7df03 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
@@ -158,6 +158,20 @@  SRC_URI:append:tc = " \
     file://0021-arm_ffa-add-support-for-FFA-v1.1.patch \
     file://0022-coresight-etm4x-Save-restore-TRFCR_EL1.patch \
     file://0023-coresight-etm4x-Use-Trace-Filtering-controls-dynamic.patch \
+    file://0024-perf-arm-cmn-Use-irq_set_affinity.patch \
+    file://0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch \
+    file://0026-perf-arm-cmn-Account-for-NUMA-affinity.patch \
+    file://0027-perf-arm-cmn-Drop-compile-test-restriction.patch \
+    file://0028-perf-arm-cmn-Refactor-node-ID-handling.patch \
+    file://0029-perf-arm-cmn-Streamline-node-iteration.patch \
+    file://0030-drivers-perf-arm-cmn-Add-space-after.patch \
+    file://0031-perf-arm-cmn-Refactor-DTM-handling.patch \
+    file://0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch \
+    file://0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch \
+    file://0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch \
+    file://0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch \
+    file://0036-perf-arm-cmn-Support-new-IP-features.patch \
+    file://0037-perf-arm-cmn-Add-CI-700-Support.patch \
     "
 KERNEL_FEATURES:append:tc = " bsp/arm-platforms/tc.scc"
 KERNEL_FEATURES:append:tc1 = " bsp/arm-platforms/tc-autofdo.scc"
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
new file mode 100644
index 0000000..e8674c3
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
@@ -0,0 +1,74 @@ 
+From ad3c5d9224ffcd7b2e083f03441c6188d2bbef67 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 18 May 2021 11:17:28 +0200
+Subject: [PATCH 01/14] perf/arm-cmn: Use irq_set_affinity()
+
+The driver uses irq_set_affinity_hint() to set the affinity for the PMU
+interrupts, which relies on the undocumented side effect that this function
+actually sets the affinity under the hood.
+
+Setting an hint is clearly not a guarantee and for these PMU interrupts an
+affinity hint, which is supposed to guide userspace for setting affinity,
+is beyond pointless, because the affinity of these interrupts cannot be
+modified from user space.
+
+Aside of that the error checks are bogus because the only error which is
+returned from irq_set_affinity_hint() is when there is no irq descriptor
+for the interrupt number, but not when the affinity set fails. That's on
+purpose because the hint can point to an offline CPU.
+
+Replace the mindless abuse with irq_set_affinity().
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+Link: https://lore.kernel.org/r/20210518093118.277228577@linutronix.de
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/20210518093118.277228577@linutronix.de]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 46defb1dcf86..38fa6f89d0bc 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -1162,7 +1162,7 @@ static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+ 
+ 	perf_pmu_migrate_context(&cmn->pmu, cpu, target);
+ 	for (i = 0; i < cmn->num_dtcs; i++)
+-		irq_set_affinity_hint(cmn->dtc[i].irq, cpumask_of(target));
++		irq_set_affinity(cmn->dtc[i].irq, cpumask_of(target));
+ 	cmn->cpu = target;
+ 	return 0;
+ }
+@@ -1222,7 +1222,7 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
+ 		if (err)
+ 			return err;
+ 
+-		err = irq_set_affinity_hint(irq, cpumask_of(cmn->cpu));
++		err = irq_set_affinity(irq, cpumask_of(cmn->cpu));
+ 		if (err)
+ 			return err;
+ 	next:
+@@ -1568,16 +1568,11 @@ static int arm_cmn_probe(struct platform_device *pdev)
+ static int arm_cmn_remove(struct platform_device *pdev)
+ {
+ 	struct arm_cmn *cmn = platform_get_drvdata(pdev);
+-	int i;
+ 
+ 	writel_relaxed(0, cmn->dtc[0].base + CMN_DT_DTC_CTL);
+ 
+ 	perf_pmu_unregister(&cmn->pmu);
+ 	cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node);
+-
+-	for (i = 0; i < cmn->num_dtcs; i++)
+-		irq_set_affinity_hint(cmn->dtc[i].irq, NULL);
+-
+ 	return 0;
+ }
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
new file mode 100644
index 0000000..e06fb88
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
@@ -0,0 +1,46 @@ 
+From 249304c3517a38863c8e45e63d509d01bd67dead Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:50 +0000
+Subject: [PATCH 02/14] perf/arm-cmn: Fix CPU hotplug unregistration
+
+Attempting to migrate the PMU context after we've unregistered the PMU
+device, or especially if we never successfully registered it in the
+first place, is a woefully bad idea. It's also fundamentally pointless
+anyway. Make sure to unregister an instance from the hotplug handler
+*without* invoking the teardown callback.
+
+Fixes: 0ba64770a2f2 ("perf: Add Arm CMN-600 PMU driver")
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/2c221d745544774e4b07583b65b5d4d94f7e0fe4.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 38fa6f89d0bc..fe7f3e945481 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -1561,7 +1561,8 @@ static int arm_cmn_probe(struct platform_device *pdev)
+ 
+ 	err = perf_pmu_register(&cmn->pmu, name, -1);
+ 	if (err)
+-		cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node);
++		cpuhp_state_remove_instance_nocalls(arm_cmn_hp_state, &cmn->cpuhp_node);
++
+ 	return err;
+ }
+ 
+@@ -1572,7 +1573,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
+ 	writel_relaxed(0, cmn->dtc[0].base + CMN_DT_DTC_CTL);
+ 
+ 	perf_pmu_unregister(&cmn->pmu);
+-	cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node);
++	cpuhp_state_remove_instance_nocalls(arm_cmn_hp_state, &cmn->cpuhp_node);
+ 	return 0;
+ }
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
new file mode 100644
index 0000000..f93bff7
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
@@ -0,0 +1,107 @@ 
+From c4b023618252ad8c03b7ae2cc411718af285bf66 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:51 +0000
+Subject: [PATCH 03/14] perf/arm-cmn: Account for NUMA affinity
+
+On a system with multiple CMN meshes, ideally we'd want to access each
+PMU from within its own mesh, rather than with a long CML round-trip,
+wherever feasible. Since such a system is likely to be presented as
+multiple NUMA nodes, let's also hope a proximity domain is specified
+for each CMN programming interface, and use that to guide our choice
+of IRQ affinity to favour a node-local CPU where possible.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 51 +++++++++++++++++++++++++++++++-----------
+ 1 file changed, 38 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index fe7f3e945481..2146d1c0103f 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -1147,23 +1147,47 @@ static int arm_cmn_commit_txn(struct pmu *pmu)
+ 	return 0;
+ }
+ 
+-static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
++static void arm_cmn_migrate(struct arm_cmn *cmn, unsigned int cpu)
++{
++	unsigned int i;
++
++	perf_pmu_migrate_context(&cmn->pmu, cmn->cpu, cpu);
++	for (i = 0; i < cmn->num_dtcs; i++)
++		irq_set_affinity(cmn->dtc[i].irq, cpumask_of(cpu));
++	cmn->cpu = cpu;
++}
++
++static int arm_cmn_pmu_online_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
+ {
+ 	struct arm_cmn *cmn;
+-	unsigned int i, target;
++	int node;
+ 
+-	cmn = hlist_entry_safe(node, struct arm_cmn, cpuhp_node);
+-	if (cpu != cmn->cpu)
+-		return 0;
++	cmn = hlist_entry_safe(cpuhp_node, struct arm_cmn, cpuhp_node);
++	node = dev_to_node(cmn->dev);
++	if (node != NUMA_NO_NODE && cpu_to_node(cmn->cpu) != node && cpu_to_node(cpu) == node)
++		arm_cmn_migrate(cmn, cpu);
++	return 0;
++}
++
++static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
++{
++	struct arm_cmn *cmn;
++	unsigned int target;
++	int node;
++	cpumask_t mask;
+ 
+-	target = cpumask_any_but(cpu_online_mask, cpu);
+-	if (target >= nr_cpu_ids)
++	cmn = hlist_entry_safe(cpuhp_node, struct arm_cmn, cpuhp_node);
++	if (cpu != cmn->cpu)
+ 		return 0;
+ 
+-	perf_pmu_migrate_context(&cmn->pmu, cpu, target);
+-	for (i = 0; i < cmn->num_dtcs; i++)
+-		irq_set_affinity(cmn->dtc[i].irq, cpumask_of(target));
+-	cmn->cpu = target;
++	node = dev_to_node(cmn->dev);
++	if (cpumask_and(&mask, cpumask_of_node(node), cpu_online_mask) &&
++	    cpumask_andnot(&mask, &mask, cpumask_of(cpu)))
++		target = cpumask_any(&mask);
++	else
++		target = cpumask_any_but(cpu_online_mask, cpu);
++	if (target < nr_cpu_ids)
++		arm_cmn_migrate(cmn, target);
+ 	return 0;
+ }
+ 
+@@ -1532,7 +1556,7 @@ static int arm_cmn_probe(struct platform_device *pdev)
+ 	if (err)
+ 		return err;
+ 
+-	cmn->cpu = raw_smp_processor_id();
++	cmn->cpu = cpumask_local_spread(0, dev_to_node(cmn->dev));
+ 	cmn->pmu = (struct pmu) {
+ 		.module = THIS_MODULE,
+ 		.attr_groups = arm_cmn_attr_groups,
+@@ -1608,7 +1632,8 @@ static int __init arm_cmn_init(void)
+ 	int ret;
+ 
+ 	ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+-				      "perf/arm/cmn:online", NULL,
++				      "perf/arm/cmn:online",
++				      arm_cmn_pmu_online_cpu,
+ 				      arm_cmn_pmu_offline_cpu);
+ 	if (ret < 0)
+ 		return ret;
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
new file mode 100644
index 0000000..1a3e2d9
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
@@ -0,0 +1,89 @@ 
+From c3b11ad7a7e3e154a17f36c6768deab9227e28de Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:52 +0000
+Subject: [PATCH 04/14] perf/arm-cmn: Drop compile-test restriction
+
+Although CMN is currently (and overwhelmingly likely to remain) deployed
+in arm64-only (modulo userspace) systems, the 64-bit "dependency" for
+compile-testing was just laziness due to heavy reliance on readq/writeq
+accessors. Since we only need one extra include for robustness in that
+regard, let's pull that in, widen the compile-test coverage, and fix up
+the smattering of type laziness that that brings to light.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/Kconfig   |  2 +-
+ drivers/perf/arm-cmn.c | 25 +++++++++++++------------
+ 2 files changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
+index 130327ff0b0e..828a042d6a07 100644
+--- a/drivers/perf/Kconfig
++++ b/drivers/perf/Kconfig
+@@ -43,7 +43,7 @@ config ARM_CCN
+ 
+ config ARM_CMN
+ 	tristate "Arm CMN-600 PMU support"
+-	depends on ARM64 || (COMPILE_TEST && 64BIT)
++	depends on ARM64 || COMPILE_TEST
+ 	help
+ 	  Support for PMU events monitoring on the Arm CMN-600 Coherent Mesh
+ 	  Network interconnect.
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 2146d1c0103f..e9af79b5f3de 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -7,6 +7,7 @@
+ #include <linux/bitops.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
++#include <linux/io-64-nonatomic-lo-hi.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/module.h>
+@@ -122,11 +123,11 @@
+ 
+ 
+ /* Event attributes */
+-#define CMN_CONFIG_TYPE			GENMASK(15, 0)
+-#define CMN_CONFIG_EVENTID		GENMASK(23, 16)
+-#define CMN_CONFIG_OCCUPID		GENMASK(27, 24)
+-#define CMN_CONFIG_BYNODEID		BIT(31)
+-#define CMN_CONFIG_NODEID		GENMASK(47, 32)
++#define CMN_CONFIG_TYPE			GENMASK_ULL(15, 0)
++#define CMN_CONFIG_EVENTID		GENMASK_ULL(23, 16)
++#define CMN_CONFIG_OCCUPID		GENMASK_ULL(27, 24)
++#define CMN_CONFIG_BYNODEID		BIT_ULL(31)
++#define CMN_CONFIG_NODEID		GENMASK_ULL(47, 32)
+ 
+ #define CMN_EVENT_TYPE(event)		FIELD_GET(CMN_CONFIG_TYPE, (event)->attr.config)
+ #define CMN_EVENT_EVENTID(event)	FIELD_GET(CMN_CONFIG_EVENTID, (event)->attr.config)
+@@ -134,13 +135,13 @@
+ #define CMN_EVENT_BYNODEID(event)	FIELD_GET(CMN_CONFIG_BYNODEID, (event)->attr.config)
+ #define CMN_EVENT_NODEID(event)		FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
+ 
+-#define CMN_CONFIG_WP_COMBINE		GENMASK(27, 24)
+-#define CMN_CONFIG_WP_DEV_SEL		BIT(48)
+-#define CMN_CONFIG_WP_CHN_SEL		GENMASK(50, 49)
+-#define CMN_CONFIG_WP_GRP		BIT(52)
+-#define CMN_CONFIG_WP_EXCLUSIVE		BIT(53)
+-#define CMN_CONFIG1_WP_VAL		GENMASK(63, 0)
+-#define CMN_CONFIG2_WP_MASK		GENMASK(63, 0)
++#define CMN_CONFIG_WP_COMBINE		GENMASK_ULL(27, 24)
++#define CMN_CONFIG_WP_DEV_SEL		BIT_ULL(48)
++#define CMN_CONFIG_WP_CHN_SEL		GENMASK_ULL(50, 49)
++#define CMN_CONFIG_WP_GRP		BIT_ULL(52)
++#define CMN_CONFIG_WP_EXCLUSIVE		BIT_ULL(53)
++#define CMN_CONFIG1_WP_VAL		GENMASK_ULL(63, 0)
++#define CMN_CONFIG2_WP_MASK		GENMASK_ULL(63, 0)
+ 
+ #define CMN_EVENT_WP_COMBINE(event)	FIELD_GET(CMN_CONFIG_WP_COMBINE, (event)->attr.config)
+ #define CMN_EVENT_WP_DEV_SEL(event)	FIELD_GET(CMN_CONFIG_WP_DEV_SEL, (event)->attr.config)
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
new file mode 100644
index 0000000..ce4c2e5
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
@@ -0,0 +1,155 @@ 
+From 4f4a4cd7c79396fa72870ff712d15e82ebff80cf Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:53 +0000
+Subject: [PATCH 05/14] perf/arm-cmn: Refactor node ID handling
+
+Add a bit more abstraction for the places where we decompose node IDs.
+This will help keep things nice and manageable when we come to add yet
+more variables which affect the node ID format. Also use the opportunity
+to move the rest of the low-level node management helpers back up to the
+logical place they were meant to be - how they ended up buried right in
+the middle of the event-related definitions is somewhat of a mystery...
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 94 +++++++++++++++++++++++++-----------------
+ 1 file changed, 56 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index e9af79b5f3de..cee301fe0f7e 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -255,6 +255,58 @@ struct arm_cmn {
+ 
+ static int arm_cmn_hp_state;
+ 
++struct arm_cmn_nodeid {
++	u8 x;
++	u8 y;
++	u8 port;
++	u8 dev;
++};
++
++static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
++{
++	int dim = max(cmn->mesh_x, cmn->mesh_y);
++
++	return dim > 4 ? 3 : 2;
++}
++
++static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
++{
++	struct arm_cmn_nodeid nid;
++	int bits = arm_cmn_xyidbits(cmn);
++
++	nid.x = CMN_NODEID_X(id, bits);
++	nid.y = CMN_NODEID_Y(id, bits);
++	nid.port = CMN_NODEID_PID(id);
++	nid.dev = CMN_NODEID_DEVID(id);
++
++	return nid;
++}
++
++static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
++				    struct arm_cmn_node *dn)
++{
++	struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
++	int xp_idx = cmn->mesh_x * nid.y + nid.x;
++
++	dn->to_xp = (cmn->xps + xp_idx) - dn;
++}
++
++static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
++{
++	return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
++}
++
++static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
++					 enum cmn_node_type type)
++{
++	int i;
++
++	for (i = 0; i < cmn->num_dns; i++)
++		if (cmn->dns[i].type == type)
++			return &cmn->dns[i];
++	return NULL;
++}
++
+ struct arm_cmn_hw_event {
+ 	struct arm_cmn_node *dn;
+ 	u64 dtm_idx[2];
+@@ -295,38 +347,6 @@ struct arm_cmn_format_attr {
+ 	int config;
+ };
+ 
+-static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
+-{
+-	return cmn->mesh_x > 4 || cmn->mesh_y > 4 ? 3 : 2;
+-}
+-
+-static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
+-				    struct arm_cmn_node *dn)
+-{
+-	int bits = arm_cmn_xyidbits(cmn);
+-	int x = CMN_NODEID_X(dn->id, bits);
+-	int y = CMN_NODEID_Y(dn->id, bits);
+-	int xp_idx = cmn->mesh_x * y + x;
+-
+-	dn->to_xp = (cmn->xps + xp_idx) - dn;
+-}
+-
+-static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
+-{
+-	return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
+-}
+-
+-static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
+-					 enum cmn_node_type type)
+-{
+-	int i;
+-
+-	for (i = 0; i < cmn->num_dns; i++)
+-		if (cmn->dns[i].type == type)
+-			return &cmn->dns[i];
+-	return NULL;
+-}
+-
+ #define CMN_EVENT_ATTR(_name, _type, _eventid, _occupid)		\
+ 	(&((struct arm_cmn_event_attr[]) {{				\
+ 		.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL),	\
+@@ -966,11 +986,10 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 	}
+ 
+ 	if (!hw->num_dns) {
+-		int bits = arm_cmn_xyidbits(cmn);
++		struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, nodeid);
+ 
+ 		dev_dbg(cmn->dev, "invalid node 0x%x (%d,%d,%d,%d) type 0x%x\n",
+-			nodeid, CMN_NODEID_X(nodeid, bits), CMN_NODEID_Y(nodeid, bits),
+-			CMN_NODEID_PID(nodeid), CMN_NODEID_DEVID(nodeid), type);
++			nodeid, nid.x, nid.y, nid.port, nid.dev, type);
+ 		return -EINVAL;
+ 	}
+ 	/*
+@@ -1068,11 +1087,10 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 			dn->wp_event[wp_idx] = dtc_idx;
+ 			writel_relaxed(cfg, dn->pmu_base + CMN_DTM_WPn_CONFIG(wp_idx));
+ 		} else {
+-			unsigned int port = CMN_NODEID_PID(dn->id);
+-			unsigned int dev = CMN_NODEID_DEVID(dn->id);
++			struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ 
+ 			input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
+-				    (port << 4) + (dev << 2);
++				    (nid.port << 4) + (nid.dev << 2);
+ 
+ 			if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
+ 				int occupid = CMN_EVENT_OCCUPID(event);
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
new file mode 100644
index 0000000..fbe49b2
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
@@ -0,0 +1,118 @@ 
+From 1b8e1ce0ebaa02c4cb7fa615b28c6905b0884e41 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:54 +0000
+Subject: [PATCH 06/14] perf/arm-cmn: Streamline node iteration
+
+Refactor the places where we scan through the set of nodes to switch
+from explicit array indexing to pointer-based iteration. This leads to
+slightly simpler object code, but also makes the source less dense and
+more pleasant for further development. It also unearths an almost-bug
+in arm_cmn_event_init() where we've been depending on the "array index"
+of NULL relative to cmn->dns being a sufficiently large number, yuck.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 33 ++++++++++++++++++++-------------
+ 1 file changed, 20 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index cee301fe0f7e..77ebed7fae08 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -299,11 +299,11 @@ static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
+ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
+ 					 enum cmn_node_type type)
+ {
+-	int i;
++	struct arm_cmn_node *dn;
+ 
+-	for (i = 0; i < cmn->num_dns; i++)
+-		if (cmn->dns[i].type == type)
+-			return &cmn->dns[i];
++	for (dn = cmn->dns; dn->type; dn++)
++		if (dn->type == type)
++			return dn;
+ 	return NULL;
+ }
+ 
+@@ -941,8 +941,8 @@ static int arm_cmn_event_init(struct perf_event *event)
+ {
+ 	struct arm_cmn *cmn = to_cmn(event->pmu);
+ 	struct arm_cmn_hw_event *hw = to_cmn_hw(event);
++	struct arm_cmn_node *dn;
+ 	enum cmn_node_type type;
+-	unsigned int i;
+ 	bool bynodeid;
+ 	u16 nodeid, eventid;
+ 
+@@ -974,10 +974,12 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 	nodeid = CMN_EVENT_NODEID(event);
+ 
+ 	hw->dn = arm_cmn_node(cmn, type);
+-	for (i = hw->dn - cmn->dns; i < cmn->num_dns && cmn->dns[i].type == type; i++) {
++	if (!hw->dn)
++		return -EINVAL;
++	for (dn = hw->dn; dn->type == type; dn++) {
+ 		if (!bynodeid) {
+ 			hw->num_dns++;
+-		} else if (cmn->dns[i].id != nodeid) {
++		} else if (dn->id != nodeid) {
+ 			hw->dn++;
+ 		} else {
+ 			hw->num_dns = 1;
+@@ -1332,7 +1334,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ 
+ 	cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
+ 
+-	for (dn = cmn->dns; dn < cmn->dns + cmn->num_dns; dn++) {
++	for (dn = cmn->dns; dn->type; dn++) {
+ 		if (dn->type != CMN_TYPE_XP)
+ 			arm_cmn_init_node_to_xp(cmn, dn);
+ 		else if (cmn->num_dtcs == 1)
+@@ -1382,6 +1384,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	u32 xp_offset[CMN_MAX_XPS];
+ 	u64 reg;
+ 	int i, j;
++	size_t sz;
+ 
+ 	cfg_region = cmn->base + rgn_offset;
+ 	reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
+@@ -1408,14 +1411,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		cmn->num_dns += FIELD_GET(CMN_CI_CHILD_COUNT, reg);
+ 	}
+ 
+-	/* Cheeky +1 to help terminate pointer-based iteration */
+-	cmn->dns = devm_kcalloc(cmn->dev, cmn->num_dns + 1,
+-				sizeof(*cmn->dns), GFP_KERNEL);
+-	if (!cmn->dns)
++	/* Cheeky +1 to help terminate pointer-based iteration later */
++	dn = devm_kcalloc(cmn->dev, cmn->num_dns + 1, sizeof(*dn), GFP_KERNEL);
++	if (!dn)
+ 		return -ENOMEM;
+ 
+ 	/* Pass 2: now we can actually populate the nodes */
+-	dn = cmn->dns;
++	cmn->dns = dn;
+ 	for (i = 0; i < cmn->num_xps; i++) {
+ 		void __iomem *xp_region = cmn->base + xp_offset[i];
+ 		struct arm_cmn_node *xp = dn++;
+@@ -1484,6 +1486,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	/* Correct for any nodes we skipped */
+ 	cmn->num_dns = dn - cmn->dns;
+ 
++	sz = (void *)(dn + 1) - (void *)cmn->dns;
++	dn = devm_krealloc(cmn->dev, cmn->dns, sz, GFP_KERNEL);
++	if (dn)
++		cmn->dns = dn;
++
+ 	/*
+ 	 * If mesh_x wasn't set during discovery then we never saw
+ 	 * an XP at (0,1), thus we must have an Nx1 configuration.
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
new file mode 100644
index 0000000..3b11192
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
@@ -0,0 +1,34 @@ 
+From c3e137a2231f434f623593b6951c7575d22e1cdb Mon Sep 17 00:00:00 2001
+From: Junhao He <hejunhao2@hisilicon.com>
+Date: Tue, 11 May 2021 20:27:33 +0800
+Subject: [PATCH 07/14] drivers/perf: arm-cmn: Add space after ','
+
+Fix a warning from checkpatch.pl.
+
+ERROR: space required after that ',' (ctx:VxV)
+
+Signed-off-by: Junhao He <hejunhao2@hisilicon.com>
+Signed-off-by: Jay Fang <f.fangjian@huawei.com>
+
+Upstream-Status: Backport [https://lore.kernel.org/all/1620736054-58412-4-git-send-email-f.fangjian@huawei.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 77ebed7fae08..e9f27f7776a2 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -32,7 +32,7 @@
+ #define CMN_CI_CHILD_COUNT		GENMASK_ULL(15, 0)
+ #define CMN_CI_CHILD_PTR_OFFSET		GENMASK_ULL(31, 16)
+ 
+-#define CMN_CHILD_NODE_ADDR		GENMASK(27,0)
++#define CMN_CHILD_NODE_ADDR		GENMASK(27, 0)
+ #define CMN_CHILD_NODE_EXTERNAL		BIT(31)
+ 
+ #define CMN_ADDR_NODE_PTR		GENMASK(27, 14)
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
new file mode 100644
index 0000000..6a68a79
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
@@ -0,0 +1,406 @@ 
+From 79bbc3eeee54b2e039dd4822e4a643e71adfbb04 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:55 +0000
+Subject: [PATCH 08/14] perf/arm-cmn: Refactor DTM handling
+
+Untangle DTMs from XPs into a dedicated abstraction. This helps make
+things a little more obvious and robust, but primarily paves the way
+for further development where new IPs can grow extra DTMs per XP.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 169 +++++++++++++++++++++--------------------
+ 1 file changed, 87 insertions(+), 82 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index e9f27f7776a2..2ae3e92690a7 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -35,14 +35,9 @@
+ #define CMN_CHILD_NODE_ADDR		GENMASK(27, 0)
+ #define CMN_CHILD_NODE_EXTERNAL		BIT(31)
+ 
+-#define CMN_ADDR_NODE_PTR		GENMASK(27, 14)
+-
+-#define CMN_NODE_PTR_DEVID(ptr)		(((ptr) >> 2) & 3)
+-#define CMN_NODE_PTR_PID(ptr)		((ptr) & 1)
+-#define CMN_NODE_PTR_X(ptr, bits)	((ptr) >> (6 + (bits)))
+-#define CMN_NODE_PTR_Y(ptr, bits)	(((ptr) >> 6) & ((1U << (bits)) - 1))
+-
+-#define CMN_MAX_XPS			(8 * 8)
++#define CMN_MAX_DIMENSION		8
++#define CMN_MAX_XPS			(CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
++#define CMN_MAX_DTMS			CMN_MAX_XPS
+ 
+ /* The CFG node has one other useful purpose */
+ #define CMN_CFGM_PERIPH_ID_2		0x0010
+@@ -190,32 +185,32 @@ struct arm_cmn_node {
+ 	u16 id, logid;
+ 	enum cmn_node_type type;
+ 
++	int dtm;
+ 	union {
+-		/* Device node */
++		/* DN/HN-F/CXHA */
+ 		struct {
+-			int to_xp;
+-			/* DN/HN-F/CXHA */
+-			unsigned int occupid_val;
+-			unsigned int occupid_count;
++			u8 occupid_val;
++			u8 occupid_count;
+ 		};
+ 		/* XP */
+-		struct {
+-			int dtc;
+-			u32 pmu_config_low;
+-			union {
+-				u8 input_sel[4];
+-				__le32 pmu_config_high;
+-			};
+-			s8 wp_event[4];
+-		};
++		int dtc;
+ 	};
+-
+ 	union {
+ 		u8 event[4];
+ 		__le32 event_sel;
+ 	};
+ };
+ 
++struct arm_cmn_dtm {
++	void __iomem *base;
++	u32 pmu_config_low;
++	union {
++		u8 input_sel[4];
++		__le32 pmu_config_high;
++	};
++	s8 wp_event[4];
++};
++
+ struct arm_cmn_dtc {
+ 	void __iomem *base;
+ 	int irq;
+@@ -241,6 +236,7 @@ struct arm_cmn {
+ 	struct arm_cmn_node *xps;
+ 	struct arm_cmn_node *dns;
+ 
++	struct arm_cmn_dtm *dtms;
+ 	struct arm_cmn_dtc *dtc;
+ 	unsigned int num_dtcs;
+ 
+@@ -282,20 +278,14 @@ static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
+ 	return nid;
+ }
+ 
+-static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
+-				    struct arm_cmn_node *dn)
++static struct arm_cmn_node *arm_cmn_node_to_xp(const struct arm_cmn *cmn,
++					       const struct arm_cmn_node *dn)
+ {
+ 	struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ 	int xp_idx = cmn->mesh_x * nid.y + nid.x;
+ 
+-	dn->to_xp = (cmn->xps + xp_idx) - dn;
+-}
+-
+-static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
+-{
+-	return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
++	return cmn->xps + xp_idx;
+ }
+-
+ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
+ 					 enum cmn_node_type type)
+ {
+@@ -706,9 +696,9 @@ static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
+ 
+ 	offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
+ 	for_each_hw_dn(hw, dn, i) {
+-		struct arm_cmn_node *xp = arm_cmn_node_to_xp(dn);
++		struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
+ 		int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+-		u64 reg = readq_relaxed(xp->pmu_base + offset);
++		u64 reg = readq_relaxed(dtm->base + offset);
+ 		u16 dtm_count = reg >> (dtm_idx * 16);
+ 
+ 		count += dtm_count;
+@@ -835,9 +825,9 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
+ }
+ 
+ struct arm_cmn_val {
+-	u8 dtm_count[CMN_MAX_XPS];
+-	u8 occupid[CMN_MAX_XPS];
+-	u8 wp[CMN_MAX_XPS][4];
++	u8 dtm_count[CMN_MAX_DTMS];
++	u8 occupid[CMN_MAX_DTMS];
++	u8 wp[CMN_MAX_DTMS][4];
+ 	int dtc_count;
+ 	bool cycles;
+ };
+@@ -866,16 +856,16 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
+ 		occupid = 0;
+ 
+ 	for_each_hw_dn(hw, dn, i) {
+-		int wp_idx, xp = arm_cmn_node_to_xp(dn)->logid;
++		int wp_idx, dtm = dn->dtm;
+ 
+-		val->dtm_count[xp]++;
+-		val->occupid[xp] = occupid;
++		val->dtm_count[dtm]++;
++		val->occupid[dtm] = occupid;
+ 
+ 		if (type != CMN_TYPE_WP)
+ 			continue;
+ 
+ 		wp_idx = arm_cmn_wp_idx(event);
+-		val->wp[xp][wp_idx] = CMN_EVENT_WP_COMBINE(event) + 1;
++		val->wp[dtm][wp_idx] = CMN_EVENT_WP_COMBINE(event) + 1;
+ 	}
+ }
+ 
+@@ -914,22 +904,22 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 		occupid = 0;
+ 
+ 	for_each_hw_dn(hw, dn, i) {
+-		int wp_idx, wp_cmb, xp = arm_cmn_node_to_xp(dn)->logid;
++		int wp_idx, wp_cmb, dtm = dn->dtm;
+ 
+-		if (val.dtm_count[xp] == CMN_DTM_NUM_COUNTERS)
++		if (val.dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
+ 			return -EINVAL;
+ 
+-		if (occupid && val.occupid[xp] && occupid != val.occupid[xp])
++		if (occupid && val.occupid[dtm] && occupid != val.occupid[dtm])
+ 			return -EINVAL;
+ 
+ 		if (type != CMN_TYPE_WP)
+ 			continue;
+ 
+ 		wp_idx = arm_cmn_wp_idx(event);
+-		if (val.wp[xp][wp_idx])
++		if (val.wp[dtm][wp_idx])
+ 			return -EINVAL;
+ 
+-		wp_cmb = val.wp[xp][wp_idx ^ 1];
++		wp_cmb = val.wp[dtm][wp_idx ^ 1];
+ 		if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
+ 			return -EINVAL;
+ 	}
+@@ -1010,17 +1000,17 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
+ 	enum cmn_node_type type = CMN_EVENT_TYPE(event);
+ 
+ 	while (i--) {
+-		struct arm_cmn_node *xp = arm_cmn_node_to_xp(hw->dn + i);
++		struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm];
+ 		unsigned int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+ 
+ 		if (type == CMN_TYPE_WP)
+-			hw->dn[i].wp_event[arm_cmn_wp_idx(event)] = -1;
++			dtm->wp_event[arm_cmn_wp_idx(event)] = -1;
+ 
+ 		if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
+ 			hw->dn[i].occupid_count--;
+ 
+-		xp->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
+-		writel_relaxed(xp->pmu_config_low, xp->pmu_base + CMN_DTM_PMU_CONFIG);
++		dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
++		writel_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
+ 	}
+ 	memset(hw->dtm_idx, 0, sizeof(hw->dtm_idx));
+ 
+@@ -1062,12 +1052,12 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 
+ 	/* ...then the local counters to feed it. */
+ 	for_each_hw_dn(hw, dn, i) {
+-		struct arm_cmn_node *xp = arm_cmn_node_to_xp(dn);
++		struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
+ 		unsigned int dtm_idx, shift;
+ 		u64 reg;
+ 
+ 		dtm_idx = 0;
+-		while (xp->pmu_config_low & CMN__PMEVCNT_PAIRED(dtm_idx))
++		while (dtm->pmu_config_low & CMN__PMEVCNT_PAIRED(dtm_idx))
+ 			if (++dtm_idx == CMN_DTM_NUM_COUNTERS)
+ 				goto free_dtms;
+ 
+@@ -1077,17 +1067,17 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 			int tmp, wp_idx = arm_cmn_wp_idx(event);
+ 			u32 cfg = arm_cmn_wp_config(event);
+ 
+-			if (dn->wp_event[wp_idx] >= 0)
++			if (dtm->wp_event[wp_idx] >= 0)
+ 				goto free_dtms;
+ 
+-			tmp = dn->wp_event[wp_idx ^ 1];
++			tmp = dtm->wp_event[wp_idx ^ 1];
+ 			if (tmp >= 0 && CMN_EVENT_WP_COMBINE(event) !=
+ 					CMN_EVENT_WP_COMBINE(dtc->counters[tmp]))
+ 				goto free_dtms;
+ 
+ 			input_sel = CMN__PMEVCNT0_INPUT_SEL_WP + wp_idx;
+-			dn->wp_event[wp_idx] = dtc_idx;
+-			writel_relaxed(cfg, dn->pmu_base + CMN_DTM_WPn_CONFIG(wp_idx));
++			dtm->wp_event[wp_idx] = dtc_idx;
++			writel_relaxed(cfg, dtm->base + CMN_DTM_WPn_CONFIG(wp_idx));
+ 		} else {
+ 			struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ 
+@@ -1095,7 +1085,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 				    (nid.port << 4) + (nid.dev << 2);
+ 
+ 			if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
+-				int occupid = CMN_EVENT_OCCUPID(event);
++				u8 occupid = CMN_EVENT_OCCUPID(event);
+ 
+ 				if (dn->occupid_count == 0) {
+ 					dn->occupid_val = occupid;
+@@ -1110,13 +1100,13 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 
+ 		arm_cmn_set_index(hw->dtm_idx, i, dtm_idx);
+ 
+-		xp->input_sel[dtm_idx] = input_sel;
++		dtm->input_sel[dtm_idx] = input_sel;
+ 		shift = CMN__PMEVCNTn_GLOBAL_NUM_SHIFT(dtm_idx);
+-		xp->pmu_config_low &= ~(CMN__PMEVCNT0_GLOBAL_NUM << shift);
+-		xp->pmu_config_low |= FIELD_PREP(CMN__PMEVCNT0_GLOBAL_NUM, dtc_idx) << shift;
+-		xp->pmu_config_low |= CMN__PMEVCNT_PAIRED(dtm_idx);
+-		reg = (u64)le32_to_cpu(xp->pmu_config_high) << 32 | xp->pmu_config_low;
+-		writeq_relaxed(reg, xp->pmu_base + CMN_DTM_PMU_CONFIG);
++		dtm->pmu_config_low &= ~(CMN__PMEVCNT0_GLOBAL_NUM << shift);
++		dtm->pmu_config_low |= FIELD_PREP(CMN__PMEVCNT0_GLOBAL_NUM, dtc_idx) << shift;
++		dtm->pmu_config_low |= CMN__PMEVCNT_PAIRED(dtm_idx);
++		reg = (u64)le32_to_cpu(dtm->pmu_config_high) << 32 | dtm->pmu_config_low;
++		writeq_relaxed(reg, dtm->base + CMN_DTM_PMU_CONFIG);
+ 	}
+ 
+ 	/* Go go go! */
+@@ -1276,23 +1266,22 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
+ 	return 0;
+ }
+ 
+-static void arm_cmn_init_dtm(struct arm_cmn_node *xp)
++static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp)
+ {
+ 	int i;
+ 
++	dtm->base = xp->pmu_base;
++	dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
+ 	for (i = 0; i < 4; i++) {
+-		xp->wp_event[i] = -1;
+-		writeq_relaxed(0, xp->pmu_base + CMN_DTM_WPn_MASK(i));
+-		writeq_relaxed(~0ULL, xp->pmu_base + CMN_DTM_WPn_VAL(i));
++		dtm->wp_event[i] = -1;
++		writeq_relaxed(0, dtm->base + CMN_DTM_WPn_MASK(i));
++		writeq_relaxed(~0ULL, dtm->base + CMN_DTM_WPn_VAL(i));
+ 	}
+-	xp->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
+-	xp->dtc = -1;
+ }
+ 
+ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int idx)
+ {
+ 	struct arm_cmn_dtc *dtc = cmn->dtc + idx;
+-	struct arm_cmn_node *xp;
+ 
+ 	dtc->base = dn->pmu_base - CMN_PMU_OFFSET;
+ 	dtc->irq = platform_get_irq(to_platform_device(cmn->dev), idx);
+@@ -1303,10 +1292,6 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id
+ 	writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR);
+ 	writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
+ 
+-	/* We do at least know that a DTC's XP must be in that DTC's domain */
+-	xp = arm_cmn_node_to_xp(dn);
+-	xp->dtc = idx;
+-
+ 	return 0;
+ }
+ 
+@@ -1323,7 +1308,7 @@ static int arm_cmn_node_cmp(const void *a, const void *b)
+ 
+ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ {
+-	struct arm_cmn_node *dn;
++	struct arm_cmn_node *dn, *xp;
+ 	int dtc_idx = 0;
+ 
+ 	cmn->dtc = devm_kcalloc(cmn->dev, cmn->num_dtcs, sizeof(cmn->dtc[0]), GFP_KERNEL);
+@@ -1335,13 +1320,24 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ 	cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
+ 
+ 	for (dn = cmn->dns; dn->type; dn++) {
+-		if (dn->type != CMN_TYPE_XP)
+-			arm_cmn_init_node_to_xp(cmn, dn);
+-		else if (cmn->num_dtcs == 1)
+-			dn->dtc = 0;
++		if (dn->type == CMN_TYPE_XP) {
++			if (dn->dtc < 0 && cmn->num_dtcs == 1)
++				dn->dtc = 0;
++			continue;
++		}
+ 
+-		if (dn->type == CMN_TYPE_DTC)
+-			arm_cmn_init_dtc(cmn, dn, dtc_idx++);
++		xp = arm_cmn_node_to_xp(cmn, dn);
++		dn->dtm = xp->dtm;
++
++		if (dn->type == CMN_TYPE_DTC) {
++			int err;
++			/* We do at least know that a DTC's XP must be in that DTC's domain */
++			if (xp->dtc < 0)
++				xp->dtc = dtc_idx;
++			err = arm_cmn_init_dtc(cmn, dn, dtc_idx++);
++			if (err)
++				return err;
++		}
+ 
+ 		/* To the PMU, RN-Ds don't add anything over RN-Is, so smoosh them together */
+ 		if (dn->type == CMN_TYPE_RND)
+@@ -1380,6 +1376,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ {
+ 	void __iomem *cfg_region;
+ 	struct arm_cmn_node cfg, *dn;
++	struct arm_cmn_dtm *dtm;
+ 	u16 child_count, child_poff;
+ 	u32 xp_offset[CMN_MAX_XPS];
+ 	u64 reg;
+@@ -1416,14 +1413,18 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	if (!dn)
+ 		return -ENOMEM;
+ 
++	dtm = devm_kcalloc(cmn->dev, cmn->num_xps, sizeof(*dtm), GFP_KERNEL);
++	if (!dtm)
++		return -ENOMEM;
++
+ 	/* Pass 2: now we can actually populate the nodes */
+ 	cmn->dns = dn;
++	cmn->dtms = dtm;
+ 	for (i = 0; i < cmn->num_xps; i++) {
+ 		void __iomem *xp_region = cmn->base + xp_offset[i];
+ 		struct arm_cmn_node *xp = dn++;
+ 
+ 		arm_cmn_init_node_info(cmn, xp_offset[i], xp);
+-		arm_cmn_init_dtm(xp);
+ 		/*
+ 		 * Thanks to the order in which XP logical IDs seem to be
+ 		 * assigned, we can handily infer the mesh X dimension by
+@@ -1433,6 +1434,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		if (xp->id == (1 << 3))
+ 			cmn->mesh_x = xp->logid;
+ 
++		xp->dtc = -1;
++		xp->dtm = dtm - cmn->dtms;
++		arm_cmn_init_dtm(dtm++, xp);
++
+ 		reg = readq_relaxed(xp_region + CMN_CHILD_INFO);
+ 		child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
+ 		child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
new file mode 100644
index 0000000..af33468
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
@@ -0,0 +1,56 @@ 
+From a63878c01597e21451c2b3f239cbf0a2fbdeeadf Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:56 +0000
+Subject: [PATCH 09/14] perf/arm-cmn: Optimise DTM counter reads
+
+When multiple nodes of the same type are connected to the same XP
+(particularly in CAL configurations), it seems that they are likely
+to be consecutive in logical ID. Therefore, we're likely to gain a
+small benefit from an easy tweak to optimise out consecutive reads
+of the same set of DTM counters for an aggregated event.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 2ae3e92690a7..5fa31ebc1fce 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -690,18 +690,19 @@ static void arm_cmn_pmu_disable(struct pmu *pmu)
+ static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
+ 			    bool snapshot)
+ {
++	struct arm_cmn_dtm *dtm = NULL;
+ 	struct arm_cmn_node *dn;
+-	unsigned int i, offset;
+-	u64 count = 0;
++	unsigned int i, offset, dtm_idx;
++	u64 reg, count = 0;
+ 
+ 	offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
+ 	for_each_hw_dn(hw, dn, i) {
+-		struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
+-		int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+-		u64 reg = readq_relaxed(dtm->base + offset);
+-		u16 dtm_count = reg >> (dtm_idx * 16);
+-
+-		count += dtm_count;
++		if (dtm != &cmn->dtms[dn->dtm]) {
++			dtm = &cmn->dtms[dn->dtm];
++			reg = readq_relaxed(dtm->base + offset);
++		}
++		dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
++		count += (u16)(reg >> (dtm_idx * 16));
+ 	}
+ 	return count;
+ }
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
new file mode 100644
index 0000000..56334e8
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
@@ -0,0 +1,111 @@ 
+From 782b7cd98e6a6b8c5fcd9e20f5c534617b1f04d3 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:57 +0000
+Subject: [PATCH 10/14] perf/arm-cmn: Optimise DTC counter accesses
+
+In cases where we do know which DTC domain a node belongs to, we can
+skip initialising or reading the global count in DTCs where we know
+it won't change. The machinery to achieve that is mostly in place
+already, so finish hooking it up by converting the vestigial domain
+tracking to propagate suitable bitmaps all the way through to events.
+
+Note that this does not allow allocating such an unused counter to a
+different event on that DTC, because that is a flippin' nightmare.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 29 ++++++++++++-----------------
+ 1 file changed, 12 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 5fa31ebc1fce..2204d6500814 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -193,7 +193,7 @@ struct arm_cmn_node {
+ 			u8 occupid_count;
+ 		};
+ 		/* XP */
+-		int dtc;
++		u8 dtc;
+ 	};
+ 	union {
+ 		u8 event[4];
+@@ -968,14 +968,14 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 	if (!hw->dn)
+ 		return -EINVAL;
+ 	for (dn = hw->dn; dn->type == type; dn++) {
+-		if (!bynodeid) {
+-			hw->num_dns++;
+-		} else if (dn->id != nodeid) {
++		if (bynodeid && dn->id != nodeid) {
+ 			hw->dn++;
+-		} else {
+-			hw->num_dns = 1;
+-			break;
++			continue;
+ 		}
++		hw->dtcs_used |= arm_cmn_node_to_xp(cmn, dn)->dtc;
++		hw->num_dns++;
++		if (bynodeid)
++			break;
+ 	}
+ 
+ 	if (!hw->num_dns) {
+@@ -985,11 +985,6 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 			nodeid, nid.x, nid.y, nid.port, nid.dev, type);
+ 		return -EINVAL;
+ 	}
+-	/*
+-	 * By assuming events count in all DTC domains, we cunningly avoid
+-	 * needing to know anything about how XPs are assigned to domains.
+-	 */
+-	hw->dtcs_used = (1U << cmn->num_dtcs) - 1;
+ 
+ 	return arm_cmn_validate_group(event);
+ }
+@@ -1311,6 +1306,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ {
+ 	struct arm_cmn_node *dn, *xp;
+ 	int dtc_idx = 0;
++	u8 dtcs_present = (1 << cmn->num_dtcs) - 1;
+ 
+ 	cmn->dtc = devm_kcalloc(cmn->dev, cmn->num_dtcs, sizeof(cmn->dtc[0]), GFP_KERNEL);
+ 	if (!cmn->dtc)
+@@ -1322,8 +1318,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ 
+ 	for (dn = cmn->dns; dn->type; dn++) {
+ 		if (dn->type == CMN_TYPE_XP) {
+-			if (dn->dtc < 0 && cmn->num_dtcs == 1)
+-				dn->dtc = 0;
++			dn->dtc &= dtcs_present;
+ 			continue;
+ 		}
+ 
+@@ -1333,8 +1328,8 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ 		if (dn->type == CMN_TYPE_DTC) {
+ 			int err;
+ 			/* We do at least know that a DTC's XP must be in that DTC's domain */
+-			if (xp->dtc < 0)
+-				xp->dtc = dtc_idx;
++			if (xp->dtc == 0xf)
++				xp->dtc = 1 << dtc_idx;
+ 			err = arm_cmn_init_dtc(cmn, dn, dtc_idx++);
+ 			if (err)
+ 				return err;
+@@ -1435,7 +1430,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		if (xp->id == (1 << 3))
+ 			cmn->mesh_x = xp->logid;
+ 
+-		xp->dtc = -1;
++		xp->dtc = 0xf;
+ 		xp->dtm = dtm - cmn->dtms;
+ 		arm_cmn_init_dtm(dtm++, xp);
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
new file mode 100644
index 0000000..06adc56
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
@@ -0,0 +1,108 @@ 
+From d919e8bcbb790018e097cb8a01e7c840dcdb82aa Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:58 +0000
+Subject: [PATCH 11/14] perf/arm-cmn: Move group validation data off-stack
+
+With the value of CMN_MAX_DTMS increasing significantly, our validation
+data structure is set to get quite big. Technically we could pack it at
+least twice as densely, since we only need around 19 bits of information
+per DTM, but that makes the code even more mind-bogglingly impenetrable,
+and even half of "quite big" may still be uncomfortably large for a
+stack frame (~1KB). Just move it to an off-stack allocation instead.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 43 ++++++++++++++++++++++++------------------
+ 1 file changed, 25 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 2204d6500814..b89a081d26ff 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -876,8 +876,8 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 	struct arm_cmn_node *dn;
+ 	struct perf_event *sibling, *leader = event->group_leader;
+ 	enum cmn_node_type type;
+-	struct arm_cmn_val val;
+-	int i;
++	struct arm_cmn_val *val;
++	int i, ret = -EINVAL;
+ 	u8 occupid;
+ 
+ 	if (leader == event)
+@@ -886,18 +886,22 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 	if (event->pmu != leader->pmu && !is_software_event(leader))
+ 		return -EINVAL;
+ 
+-	memset(&val, 0, sizeof(val));
++	val = kzalloc(sizeof(*val), GFP_KERNEL);
++	if (!val)
++		return -ENOMEM;
+ 
+-	arm_cmn_val_add_event(&val, leader);
++	arm_cmn_val_add_event(val, leader);
+ 	for_each_sibling_event(sibling, leader)
+-		arm_cmn_val_add_event(&val, sibling);
++		arm_cmn_val_add_event(val, sibling);
+ 
+ 	type = CMN_EVENT_TYPE(event);
+-	if (type == CMN_TYPE_DTC)
+-		return val.cycles ? -EINVAL : 0;
++	if (type == CMN_TYPE_DTC) {
++		ret = val->cycles ? -EINVAL : 0;
++		goto done;
++	}
+ 
+-	if (val.dtc_count == CMN_DT_NUM_COUNTERS)
+-		return -EINVAL;
++	if (val->dtc_count == CMN_DT_NUM_COUNTERS)
++		goto done;
+ 
+ 	if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
+ 		occupid = CMN_EVENT_OCCUPID(event) + 1;
+@@ -907,25 +911,28 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 	for_each_hw_dn(hw, dn, i) {
+ 		int wp_idx, wp_cmb, dtm = dn->dtm;
+ 
+-		if (val.dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
+-			return -EINVAL;
++		if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
++			goto done;
+ 
+-		if (occupid && val.occupid[dtm] && occupid != val.occupid[dtm])
+-			return -EINVAL;
++		if (occupid && val->occupid[dtm] && occupid != val->occupid[dtm])
++			goto done;
+ 
+ 		if (type != CMN_TYPE_WP)
+ 			continue;
+ 
+ 		wp_idx = arm_cmn_wp_idx(event);
+-		if (val.wp[dtm][wp_idx])
+-			return -EINVAL;
++		if (val->wp[dtm][wp_idx])
++			goto done;
+ 
+-		wp_cmb = val.wp[dtm][wp_idx ^ 1];
++		wp_cmb = val->wp[dtm][wp_idx ^ 1];
+ 		if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
+-			return -EINVAL;
++			goto done;
+ 	}
+ 
+-	return 0;
++	ret = 0;
++done:
++	kfree(val);
++	return ret;
+ }
+ 
+ static int arm_cmn_event_init(struct perf_event *event)
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
new file mode 100644
index 0000000..0fbc5cb
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
@@ -0,0 +1,466 @@ 
+From 7400784247be42beb996f7538547c56acd6cfa0c Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:44:59 +0000
+Subject: [PATCH 12/14] perf/arm-cmn: Demarcate CMN-600 specifics
+
+In preparation for supporting newer CMN products, let's introduce a
+means to differentiate the features and events which are specific to a
+particular IP from those which remain common to the whole family. The
+newer designs have also smoothed off some of the rough edges in terms
+of discoverability, so separate out the parts of the flow which have
+effectively now become CMN-600 quirks.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 313 +++++++++++++++++++++--------------------
+ 1 file changed, 162 insertions(+), 151 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index b89a081d26ff..92ff273fbe58 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -151,7 +151,12 @@
+ #define CMN_WP_DOWN			2
+ 
+ 
+-/* r0px probably don't exist in silicon, thankfully */
++enum cmn_model {
++	CMN_ANY = -1,
++	CMN600 = 1,
++};
++
++/* CMN-600 r0px shouldn't exist in silicon, thankfully */
+ enum cmn_revision {
+ 	CMN600_R1P0,
+ 	CMN600_R1P1,
+@@ -159,6 +164,7 @@ enum cmn_revision {
+ 	CMN600_R1P3,
+ 	CMN600_R2P0,
+ 	CMN600_R3P0,
++	CMN600_R3P1,
+ };
+ 
+ enum cmn_node_type {
+@@ -229,6 +235,7 @@ struct arm_cmn {
+ 	void __iomem *base;
+ 
+ 	enum cmn_revision rev;
++	enum cmn_model model;
+ 	u8 mesh_x;
+ 	u8 mesh_y;
+ 	u16 num_xps;
+@@ -326,6 +333,7 @@ static unsigned int arm_cmn_get_index(u64 x[], unsigned int pos)
+ 
+ struct arm_cmn_event_attr {
+ 	struct device_attribute attr;
++	enum cmn_model model;
+ 	enum cmn_node_type type;
+ 	u8 eventid;
+ 	u8 occupid;
+@@ -337,9 +345,10 @@ struct arm_cmn_format_attr {
+ 	int config;
+ };
+ 
+-#define CMN_EVENT_ATTR(_name, _type, _eventid, _occupid)		\
++#define CMN_EVENT_ATTR(_model, _name, _type, _eventid, _occupid)	\
+ 	(&((struct arm_cmn_event_attr[]) {{				\
+ 		.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL),	\
++		.model = _model,					\
+ 		.type = _type,						\
+ 		.eventid = _eventid,					\
+ 		.occupid = _occupid,					\
+@@ -386,12 +395,15 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
+ 	eattr = container_of(attr, typeof(*eattr), attr.attr);
+ 	type = eattr->type;
+ 
++	if (!(eattr->model & cmn->model))
++		return 0;
++
+ 	/* Watchpoints aren't nodes */
+ 	if (type == CMN_TYPE_WP)
+ 		type = CMN_TYPE_XP;
+ 
+ 	/* Revision-specific differences */
+-	if (cmn->rev < CMN600_R1P2) {
++	if (cmn->model == CMN600 && cmn->rev < CMN600_R1P2) {
+ 		if (type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
+ 			return 0;
+ 	}
+@@ -402,25 +414,27 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
+ 	return attr->mode;
+ }
+ 
+-#define _CMN_EVENT_DVM(_name, _event, _occup)			\
+-	CMN_EVENT_ATTR(dn_##_name, CMN_TYPE_DVM, _event, _occup)
++#define _CMN_EVENT_DVM(_model, _name, _event, _occup)		\
++	CMN_EVENT_ATTR(_model, dn_##_name, CMN_TYPE_DVM, _event, _occup)
+ #define CMN_EVENT_DTC(_name)					\
+-	CMN_EVENT_ATTR(dtc_##_name, CMN_TYPE_DTC, 0, 0)
+-#define _CMN_EVENT_HNF(_name, _event, _occup)			\
+-	CMN_EVENT_ATTR(hnf_##_name, CMN_TYPE_HNF, _event, _occup)
++	CMN_EVENT_ATTR(CMN_ANY, dtc_##_name, CMN_TYPE_DTC, 0, 0)
++#define _CMN_EVENT_HNF(_model, _name, _event, _occup)		\
++	CMN_EVENT_ATTR(_model, hnf_##_name, CMN_TYPE_HNF, _event, _occup)
+ #define CMN_EVENT_HNI(_name, _event)				\
+-	CMN_EVENT_ATTR(hni_##_name, CMN_TYPE_HNI, _event, 0)
++	CMN_EVENT_ATTR(CMN_ANY, hni_##_name, CMN_TYPE_HNI, _event, 0)
+ #define __CMN_EVENT_XP(_name, _event)				\
+-	CMN_EVENT_ATTR(mxp_##_name, CMN_TYPE_XP, _event, 0)
+-#define CMN_EVENT_SBSX(_name, _event)				\
+-	CMN_EVENT_ATTR(sbsx_##_name, CMN_TYPE_SBSX, _event, 0)
+-#define CMN_EVENT_RNID(_name, _event)				\
+-	CMN_EVENT_ATTR(rnid_##_name, CMN_TYPE_RNI, _event, 0)
+-
+-#define CMN_EVENT_DVM(_name, _event)				\
+-	_CMN_EVENT_DVM(_name, _event, 0)
+-#define CMN_EVENT_HNF(_name, _event)				\
+-	_CMN_EVENT_HNF(_name, _event, 0)
++	CMN_EVENT_ATTR(CMN_ANY, mxp_##_name, CMN_TYPE_XP, _event, 0)
++#define CMN_EVENT_SBSX(_model, _name, _event)			\
++	CMN_EVENT_ATTR(_model, sbsx_##_name, CMN_TYPE_SBSX, _event, 0)
++#define CMN_EVENT_RNID(_model, _name, _event)			\
++	CMN_EVENT_ATTR(_model, rnid_##_name, CMN_TYPE_RNI, _event, 0)
++#define CMN_EVENT_MTSX(_name, _event)				\
++	CMN_EVENT_ATTR(CMN_ANY, mtsx_##_name, CMN_TYPE_MTSX, _event, 0)
++
++#define CMN_EVENT_DVM(_model, _name, _event)			\
++	_CMN_EVENT_DVM(_model, _name, _event, 0)
++#define CMN_EVENT_HNF(_model, _name, _event)			\
++	_CMN_EVENT_HNF(_model, _name, _event, 0)
+ #define _CMN_EVENT_XP(_name, _event)				\
+ 	__CMN_EVENT_XP(e_##_name, (_event) | (0 << 2)),		\
+ 	__CMN_EVENT_XP(w_##_name, (_event) | (1 << 2)),		\
+@@ -445,115 +459,115 @@ static struct attribute *arm_cmn_event_attrs[] = {
+ 	 * slot, but our lazy short-cut of using the DTM counter index for
+ 	 * the PMU index as well happens to avoid that by construction.
+ 	 */
+-	CMN_EVENT_DVM(rxreq_dvmop,	0x01),
+-	CMN_EVENT_DVM(rxreq_dvmsync,	0x02),
+-	CMN_EVENT_DVM(rxreq_dvmop_vmid_filtered, 0x03),
+-	CMN_EVENT_DVM(rxreq_retried,	0x04),
+-	_CMN_EVENT_DVM(rxreq_trk_occupancy_all, 0x05, 0),
+-	_CMN_EVENT_DVM(rxreq_trk_occupancy_dvmop, 0x05, 1),
+-	_CMN_EVENT_DVM(rxreq_trk_occupancy_dvmsync, 0x05, 2),
+-
+-	CMN_EVENT_HNF(cache_miss,	0x01),
+-	CMN_EVENT_HNF(slc_sf_cache_access, 0x02),
+-	CMN_EVENT_HNF(cache_fill,	0x03),
+-	CMN_EVENT_HNF(pocq_retry,	0x04),
+-	CMN_EVENT_HNF(pocq_reqs_recvd,	0x05),
+-	CMN_EVENT_HNF(sf_hit,		0x06),
+-	CMN_EVENT_HNF(sf_evictions,	0x07),
+-	CMN_EVENT_HNF(dir_snoops_sent,	0x08),
+-	CMN_EVENT_HNF(brd_snoops_sent,	0x09),
+-	CMN_EVENT_HNF(slc_eviction,	0x0a),
+-	CMN_EVENT_HNF(slc_fill_invalid_way, 0x0b),
+-	CMN_EVENT_HNF(mc_retries,	0x0c),
+-	CMN_EVENT_HNF(mc_reqs,		0x0d),
+-	CMN_EVENT_HNF(qos_hh_retry,	0x0e),
+-	_CMN_EVENT_HNF(qos_pocq_occupancy_all, 0x0f, 0),
+-	_CMN_EVENT_HNF(qos_pocq_occupancy_read, 0x0f, 1),
+-	_CMN_EVENT_HNF(qos_pocq_occupancy_write, 0x0f, 2),
+-	_CMN_EVENT_HNF(qos_pocq_occupancy_atomic, 0x0f, 3),
+-	_CMN_EVENT_HNF(qos_pocq_occupancy_stash, 0x0f, 4),
+-	CMN_EVENT_HNF(pocq_addrhaz,	0x10),
+-	CMN_EVENT_HNF(pocq_atomic_addrhaz, 0x11),
+-	CMN_EVENT_HNF(ld_st_swp_adq_full, 0x12),
+-	CMN_EVENT_HNF(cmp_adq_full,	0x13),
+-	CMN_EVENT_HNF(txdat_stall,	0x14),
+-	CMN_EVENT_HNF(txrsp_stall,	0x15),
+-	CMN_EVENT_HNF(seq_full,		0x16),
+-	CMN_EVENT_HNF(seq_hit,		0x17),
+-	CMN_EVENT_HNF(snp_sent,		0x18),
+-	CMN_EVENT_HNF(sfbi_dir_snp_sent, 0x19),
+-	CMN_EVENT_HNF(sfbi_brd_snp_sent, 0x1a),
+-	CMN_EVENT_HNF(snp_sent_untrk,	0x1b),
+-	CMN_EVENT_HNF(intv_dirty,	0x1c),
+-	CMN_EVENT_HNF(stash_snp_sent,	0x1d),
+-	CMN_EVENT_HNF(stash_data_pull,	0x1e),
+-	CMN_EVENT_HNF(snp_fwded,	0x1f),
+-
+-	CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl, 0x20),
+-	CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl, 0x21),
+-	CMN_EVENT_HNI(rdt_rd_occ_cnt_ovfl, 0x22),
+-	CMN_EVENT_HNI(rdt_wr_occ_cnt_ovfl, 0x23),
+-	CMN_EVENT_HNI(wdb_occ_cnt_ovfl,	0x24),
+-	CMN_EVENT_HNI(rrt_rd_alloc,	0x25),
+-	CMN_EVENT_HNI(rrt_wr_alloc,	0x26),
+-	CMN_EVENT_HNI(rdt_rd_alloc,	0x27),
+-	CMN_EVENT_HNI(rdt_wr_alloc,	0x28),
+-	CMN_EVENT_HNI(wdb_alloc,	0x29),
+-	CMN_EVENT_HNI(txrsp_retryack,	0x2a),
+-	CMN_EVENT_HNI(arvalid_no_arready, 0x2b),
+-	CMN_EVENT_HNI(arready_no_arvalid, 0x2c),
+-	CMN_EVENT_HNI(awvalid_no_awready, 0x2d),
+-	CMN_EVENT_HNI(awready_no_awvalid, 0x2e),
+-	CMN_EVENT_HNI(wvalid_no_wready,	0x2f),
+-	CMN_EVENT_HNI(txdat_stall,	0x30),
+-	CMN_EVENT_HNI(nonpcie_serialization, 0x31),
+-	CMN_EVENT_HNI(pcie_serialization, 0x32),
+-
+-	CMN_EVENT_XP(txflit_valid,	0x01),
+-	CMN_EVENT_XP(txflit_stall,	0x02),
+-	CMN_EVENT_XP(partial_dat_flit,	0x03),
++	CMN_EVENT_DVM(CMN600, rxreq_dvmop,		0x01),
++	CMN_EVENT_DVM(CMN600, rxreq_dvmsync,		0x02),
++	CMN_EVENT_DVM(CMN600, rxreq_dvmop_vmid_filtered, 0x03),
++	CMN_EVENT_DVM(CMN600, rxreq_retried,		0x04),
++	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_all, 0x05, 0),
++	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmop, 0x05, 1),
++	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmsync, 0x05, 2),
++
++	CMN_EVENT_HNF(CMN_ANY, cache_miss,		0x01),
++	CMN_EVENT_HNF(CMN_ANY, slc_sf_cache_access,	0x02),
++	CMN_EVENT_HNF(CMN_ANY, cache_fill,		0x03),
++	CMN_EVENT_HNF(CMN_ANY, pocq_retry,		0x04),
++	CMN_EVENT_HNF(CMN_ANY, pocq_reqs_recvd,		0x05),
++	CMN_EVENT_HNF(CMN_ANY, sf_hit,			0x06),
++	CMN_EVENT_HNF(CMN_ANY, sf_evictions,		0x07),
++	CMN_EVENT_HNF(CMN_ANY, dir_snoops_sent,		0x08),
++	CMN_EVENT_HNF(CMN_ANY, brd_snoops_sent,		0x09),
++	CMN_EVENT_HNF(CMN_ANY, slc_eviction,		0x0a),
++	CMN_EVENT_HNF(CMN_ANY, slc_fill_invalid_way,	0x0b),
++	CMN_EVENT_HNF(CMN_ANY, mc_retries,		0x0c),
++	CMN_EVENT_HNF(CMN_ANY, mc_reqs,			0x0d),
++	CMN_EVENT_HNF(CMN_ANY, qos_hh_retry,		0x0e),
++	_CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_all,	0x0f, 0),
++	_CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_read, 0x0f, 1),
++	_CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_write, 0x0f, 2),
++	_CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_atomic, 0x0f, 3),
++	_CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_stash, 0x0f, 4),
++	CMN_EVENT_HNF(CMN_ANY, pocq_addrhaz,		0x10),
++	CMN_EVENT_HNF(CMN_ANY, pocq_atomic_addrhaz,	0x11),
++	CMN_EVENT_HNF(CMN_ANY, ld_st_swp_adq_full,	0x12),
++	CMN_EVENT_HNF(CMN_ANY, cmp_adq_full,		0x13),
++	CMN_EVENT_HNF(CMN_ANY, txdat_stall,		0x14),
++	CMN_EVENT_HNF(CMN_ANY, txrsp_stall,		0x15),
++	CMN_EVENT_HNF(CMN_ANY, seq_full,		0x16),
++	CMN_EVENT_HNF(CMN_ANY, seq_hit,			0x17),
++	CMN_EVENT_HNF(CMN_ANY, snp_sent,		0x18),
++	CMN_EVENT_HNF(CMN_ANY, sfbi_dir_snp_sent,	0x19),
++	CMN_EVENT_HNF(CMN_ANY, sfbi_brd_snp_sent,	0x1a),
++	CMN_EVENT_HNF(CMN_ANY, snp_sent_untrk,		0x1b),
++	CMN_EVENT_HNF(CMN_ANY, intv_dirty,		0x1c),
++	CMN_EVENT_HNF(CMN_ANY, stash_snp_sent,		0x1d),
++	CMN_EVENT_HNF(CMN_ANY, stash_data_pull,		0x1e),
++	CMN_EVENT_HNF(CMN_ANY, snp_fwded,		0x1f),
++
++	CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl,		0x20),
++	CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl,		0x21),
++	CMN_EVENT_HNI(rdt_rd_occ_cnt_ovfl,		0x22),
++	CMN_EVENT_HNI(rdt_wr_occ_cnt_ovfl,		0x23),
++	CMN_EVENT_HNI(wdb_occ_cnt_ovfl,			0x24),
++	CMN_EVENT_HNI(rrt_rd_alloc,			0x25),
++	CMN_EVENT_HNI(rrt_wr_alloc,			0x26),
++	CMN_EVENT_HNI(rdt_rd_alloc,			0x27),
++	CMN_EVENT_HNI(rdt_wr_alloc,			0x28),
++	CMN_EVENT_HNI(wdb_alloc,			0x29),
++	CMN_EVENT_HNI(txrsp_retryack,			0x2a),
++	CMN_EVENT_HNI(arvalid_no_arready,		0x2b),
++	CMN_EVENT_HNI(arready_no_arvalid,		0x2c),
++	CMN_EVENT_HNI(awvalid_no_awready,		0x2d),
++	CMN_EVENT_HNI(awready_no_awvalid,		0x2e),
++	CMN_EVENT_HNI(wvalid_no_wready,			0x2f),
++	CMN_EVENT_HNI(txdat_stall,			0x30),
++	CMN_EVENT_HNI(nonpcie_serialization,		0x31),
++	CMN_EVENT_HNI(pcie_serialization,		0x32),
++
++	CMN_EVENT_XP(txflit_valid,			0x01),
++	CMN_EVENT_XP(txflit_stall,			0x02),
++	CMN_EVENT_XP(partial_dat_flit,			0x03),
+ 	/* We treat watchpoints as a special made-up class of XP events */
+-	CMN_EVENT_ATTR(watchpoint_up, CMN_TYPE_WP, 0, 0),
+-	CMN_EVENT_ATTR(watchpoint_down, CMN_TYPE_WP, 2, 0),
+-
+-	CMN_EVENT_SBSX(rd_req,		0x01),
+-	CMN_EVENT_SBSX(wr_req,		0x02),
+-	CMN_EVENT_SBSX(cmo_req,		0x03),
+-	CMN_EVENT_SBSX(txrsp_retryack,	0x04),
+-	CMN_EVENT_SBSX(txdat_flitv,	0x05),
+-	CMN_EVENT_SBSX(txrsp_flitv,	0x06),
+-	CMN_EVENT_SBSX(rd_req_trkr_occ_cnt_ovfl, 0x11),
+-	CMN_EVENT_SBSX(wr_req_trkr_occ_cnt_ovfl, 0x12),
+-	CMN_EVENT_SBSX(cmo_req_trkr_occ_cnt_ovfl, 0x13),
+-	CMN_EVENT_SBSX(wdb_occ_cnt_ovfl, 0x14),
+-	CMN_EVENT_SBSX(rd_axi_trkr_occ_cnt_ovfl, 0x15),
+-	CMN_EVENT_SBSX(cmo_axi_trkr_occ_cnt_ovfl, 0x16),
+-	CMN_EVENT_SBSX(arvalid_no_arready, 0x21),
+-	CMN_EVENT_SBSX(awvalid_no_awready, 0x22),
+-	CMN_EVENT_SBSX(wvalid_no_wready, 0x23),
+-	CMN_EVENT_SBSX(txdat_stall,	0x24),
+-	CMN_EVENT_SBSX(txrsp_stall,	0x25),
+-
+-	CMN_EVENT_RNID(s0_rdata_beats,	0x01),
+-	CMN_EVENT_RNID(s1_rdata_beats,	0x02),
+-	CMN_EVENT_RNID(s2_rdata_beats,	0x03),
+-	CMN_EVENT_RNID(rxdat_flits,	0x04),
+-	CMN_EVENT_RNID(txdat_flits,	0x05),
+-	CMN_EVENT_RNID(txreq_flits_total, 0x06),
+-	CMN_EVENT_RNID(txreq_flits_retried, 0x07),
+-	CMN_EVENT_RNID(rrt_occ_ovfl,	0x08),
+-	CMN_EVENT_RNID(wrt_occ_ovfl,	0x09),
+-	CMN_EVENT_RNID(txreq_flits_replayed, 0x0a),
+-	CMN_EVENT_RNID(wrcancel_sent,	0x0b),
+-	CMN_EVENT_RNID(s0_wdata_beats,	0x0c),
+-	CMN_EVENT_RNID(s1_wdata_beats,	0x0d),
+-	CMN_EVENT_RNID(s2_wdata_beats,	0x0e),
+-	CMN_EVENT_RNID(rrt_alloc,	0x0f),
+-	CMN_EVENT_RNID(wrt_alloc,	0x10),
+-	CMN_EVENT_RNID(rdb_unord,	0x11),
+-	CMN_EVENT_RNID(rdb_replay,	0x12),
+-	CMN_EVENT_RNID(rdb_hybrid,	0x13),
+-	CMN_EVENT_RNID(rdb_ord,		0x14),
++	CMN_EVENT_ATTR(CMN_ANY, watchpoint_up, CMN_TYPE_WP, CMN_WP_UP, 0),
++	CMN_EVENT_ATTR(CMN_ANY, watchpoint_down, CMN_TYPE_WP, CMN_WP_DOWN, 0),
++
++	CMN_EVENT_SBSX(CMN_ANY, rd_req,			0x01),
++	CMN_EVENT_SBSX(CMN_ANY, wr_req,			0x02),
++	CMN_EVENT_SBSX(CMN_ANY, cmo_req,		0x03),
++	CMN_EVENT_SBSX(CMN_ANY, txrsp_retryack,		0x04),
++	CMN_EVENT_SBSX(CMN_ANY, txdat_flitv,		0x05),
++	CMN_EVENT_SBSX(CMN_ANY, txrsp_flitv,		0x06),
++	CMN_EVENT_SBSX(CMN_ANY, rd_req_trkr_occ_cnt_ovfl, 0x11),
++	CMN_EVENT_SBSX(CMN_ANY, wr_req_trkr_occ_cnt_ovfl, 0x12),
++	CMN_EVENT_SBSX(CMN_ANY, cmo_req_trkr_occ_cnt_ovfl, 0x13),
++	CMN_EVENT_SBSX(CMN_ANY, wdb_occ_cnt_ovfl,	0x14),
++	CMN_EVENT_SBSX(CMN_ANY, rd_axi_trkr_occ_cnt_ovfl, 0x15),
++	CMN_EVENT_SBSX(CMN_ANY, cmo_axi_trkr_occ_cnt_ovfl, 0x16),
++	CMN_EVENT_SBSX(CMN_ANY, arvalid_no_arready,	0x21),
++	CMN_EVENT_SBSX(CMN_ANY, awvalid_no_awready,	0x22),
++	CMN_EVENT_SBSX(CMN_ANY, wvalid_no_wready,	0x23),
++	CMN_EVENT_SBSX(CMN_ANY, txdat_stall,		0x24),
++	CMN_EVENT_SBSX(CMN_ANY, txrsp_stall,		0x25),
++
++	CMN_EVENT_RNID(CMN_ANY, s0_rdata_beats,		0x01),
++	CMN_EVENT_RNID(CMN_ANY, s1_rdata_beats,		0x02),
++	CMN_EVENT_RNID(CMN_ANY, s2_rdata_beats,		0x03),
++	CMN_EVENT_RNID(CMN_ANY, rxdat_flits,		0x04),
++	CMN_EVENT_RNID(CMN_ANY, txdat_flits,		0x05),
++	CMN_EVENT_RNID(CMN_ANY, txreq_flits_total,	0x06),
++	CMN_EVENT_RNID(CMN_ANY, txreq_flits_retried,	0x07),
++	CMN_EVENT_RNID(CMN_ANY, rrt_occ_ovfl,		0x08),
++	CMN_EVENT_RNID(CMN_ANY, wrt_occ_ovfl,		0x09),
++	CMN_EVENT_RNID(CMN_ANY, txreq_flits_replayed,	0x0a),
++	CMN_EVENT_RNID(CMN_ANY, wrcancel_sent,		0x0b),
++	CMN_EVENT_RNID(CMN_ANY, s0_wdata_beats,		0x0c),
++	CMN_EVENT_RNID(CMN_ANY, s1_wdata_beats,		0x0d),
++	CMN_EVENT_RNID(CMN_ANY, s2_wdata_beats,		0x0e),
++	CMN_EVENT_RNID(CMN_ANY, rrt_alloc,		0x0f),
++	CMN_EVENT_RNID(CMN_ANY, wrt_alloc,		0x10),
++	CMN_EVENT_RNID(CMN600, rdb_unord,		0x11),
++	CMN_EVENT_RNID(CMN600, rdb_replay,		0x12),
++	CMN_EVENT_RNID(CMN600, rdb_hybrid,		0x13),
++	CMN_EVENT_RNID(CMN600, rdb_ord,			0x14),
+ 
+ 	NULL
+ };
+@@ -1386,15 +1400,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	int i, j;
+ 	size_t sz;
+ 
+-	cfg_region = cmn->base + rgn_offset;
+-	reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
+-	cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
+-	dev_dbg(cmn->dev, "periph_id_2 revision: %d\n", cmn->rev);
+-
+ 	arm_cmn_init_node_info(cmn, rgn_offset, &cfg);
+ 	if (cfg.type != CMN_TYPE_CFG)
+ 		return -ENODEV;
+ 
++	cfg_region = cmn->base + rgn_offset;
++	reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
++	cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
++
+ 	reg = readq_relaxed(cfg_region + CMN_CHILD_INFO);
+ 	child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
+ 	child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
+@@ -1507,13 +1520,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		cmn->mesh_x = cmn->num_xps;
+ 	cmn->mesh_y = cmn->num_xps / cmn->mesh_x;
+ 
++	dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev);
+ 	dev_dbg(cmn->dev, "mesh %dx%d, ID width %d\n",
+ 		cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn));
+ 
+ 	return 0;
+ }
+ 
+-static int arm_cmn_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
++static int arm_cmn600_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
+ {
+ 	struct resource *cfg, *root;
+ 
+@@ -1540,21 +1554,11 @@ static int arm_cmn_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
+ 	return root->start - cfg->start;
+ }
+ 
+-static int arm_cmn_of_probe(struct platform_device *pdev, struct arm_cmn *cmn)
++static int arm_cmn600_of_probe(struct device_node *np)
+ {
+-	struct device_node *np = pdev->dev.of_node;
+ 	u32 rootnode;
+-	int ret;
+ 
+-	cmn->base = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(cmn->base))
+-		return PTR_ERR(cmn->base);
+-
+-	ret = of_property_read_u32(np, "arm,root-node", &rootnode);
+-	if (ret)
+-		return ret;
+-
+-	return rootnode;
++	return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode;
+ }
+ 
+ static int arm_cmn_probe(struct platform_device *pdev)
+@@ -1569,12 +1573,19 @@ static int arm_cmn_probe(struct platform_device *pdev)
+ 		return -ENOMEM;
+ 
+ 	cmn->dev = &pdev->dev;
++	cmn->model = (unsigned long)device_get_match_data(cmn->dev);
+ 	platform_set_drvdata(pdev, cmn);
+ 
+-	if (has_acpi_companion(cmn->dev))
+-		rootnode = arm_cmn_acpi_probe(pdev, cmn);
+-	else
+-		rootnode = arm_cmn_of_probe(pdev, cmn);
++	if (cmn->model == CMN600 && has_acpi_companion(cmn->dev)) {
++		rootnode = arm_cmn600_acpi_probe(pdev, cmn);
++	} else {
++		rootnode = 0;
++		cmn->base = devm_platform_ioremap_resource(pdev, 0);
++		if (IS_ERR(cmn->base))
++			return PTR_ERR(cmn->base);
++		if (cmn->model == CMN600)
++			rootnode = arm_cmn600_of_probe(pdev->dev.of_node);
++	}
+ 	if (rootnode < 0)
+ 		return rootnode;
+ 
+@@ -1637,7 +1648,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
+ 
+ #ifdef CONFIG_OF
+ static const struct of_device_id arm_cmn_of_match[] = {
+-	{ .compatible = "arm,cmn-600", },
++	{ .compatible = "arm,cmn-600", .data = (void *)CMN600 },
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
+@@ -1645,7 +1656,7 @@ MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
+ 
+ #ifdef CONFIG_ACPI
+ static const struct acpi_device_id arm_cmn_acpi_match[] = {
+-	{ "ARMHC600", },
++	{ "ARMHC600", CMN600 },
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match);
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
new file mode 100644
index 0000000..fa0c5d9
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
@@ -0,0 +1,549 @@ 
+From a10c446ba1f7516c16dd6400c9a7f5e203779a5d Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:45:00 +0000
+Subject: [PATCH 13/14] perf/arm-cmn: Support new IP features
+
+The second generation of CMN IPs add new node types and significantly
+expand the configuration space with options for extra device ports on
+edge XPs, either plumbed into the regular DTM or with extra dedicated
+DTMs to monitor them, plus larger (and smaller) mesh sizes. Add basic
+support for pulling this new information out of the hardware, piping
+it around as necessary, and handling (most of) the new choices.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/e58b495bcc7deec3882be4bac910ed0bf6979674.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 222 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 173 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 92ff273fbe58..871c86687379 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -24,7 +24,10 @@
+ #define CMN_NI_LOGICAL_ID		GENMASK_ULL(47, 32)
+ 
+ #define CMN_NODEID_DEVID(reg)		((reg) & 3)
++#define CMN_NODEID_EXT_DEVID(reg)	((reg) & 1)
+ #define CMN_NODEID_PID(reg)		(((reg) >> 2) & 1)
++#define CMN_NODEID_EXT_PID(reg)		(((reg) >> 1) & 3)
++#define CMN_NODEID_1x1_PID(reg)		(((reg) >> 2) & 7)
+ #define CMN_NODEID_X(reg, bits)		((reg) >> (3 + (bits)))
+ #define CMN_NODEID_Y(reg, bits)		(((reg) >> 3) & ((1U << (bits)) - 1))
+ 
+@@ -37,13 +40,26 @@
+ 
+ #define CMN_MAX_DIMENSION		8
+ #define CMN_MAX_XPS			(CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
+-#define CMN_MAX_DTMS			CMN_MAX_XPS
++#define CMN_MAX_DTMS			(CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
+ 
+-/* The CFG node has one other useful purpose */
++/* The CFG node has various info besides the discovery tree */
+ #define CMN_CFGM_PERIPH_ID_2		0x0010
+ #define CMN_CFGM_PID2_REVISION		GENMASK(7, 4)
+ 
+-/* PMU registers occupy the 3rd 4KB page of each node's 16KB space */
++#define CMN_CFGM_INFO_GLOBAL		0x900
++#define CMN_INFO_MULTIPLE_DTM_EN	BIT_ULL(63)
++#define CMN_INFO_RSP_VC_NUM		GENMASK_ULL(53, 52)
++#define CMN_INFO_DAT_VC_NUM		GENMASK_ULL(51, 50)
++
++/* XPs also have some local topology info which has uses too */
++#define CMN_MXP__CONNECT_INFO_P0	0x0008
++#define CMN_MXP__CONNECT_INFO_P1	0x0010
++#define CMN_MXP__CONNECT_INFO_P2	0x0028
++#define CMN_MXP__CONNECT_INFO_P3	0x0030
++#define CMN_MXP__CONNECT_INFO_P4	0x0038
++#define CMN_MXP__CONNECT_INFO_P5	0x0040
++
++/* PMU registers occupy the 3rd 4KB page of each node's region */
+ #define CMN_PMU_OFFSET			0x2000
+ 
+ /* For most nodes, this is all there is */
+@@ -53,6 +69,7 @@
+ /* DTMs live in the PMU space of XP registers */
+ #define CMN_DTM_WPn(n)			(0x1A0 + (n) * 0x18)
+ #define CMN_DTM_WPn_CONFIG(n)		(CMN_DTM_WPn(n) + 0x00)
++#define CMN_DTM_WPn_CONFIG_WP_DEV_SEL2	GENMASK_ULL(18,17)
+ #define CMN_DTM_WPn_CONFIG_WP_COMBINE	BIT(6)
+ #define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE	BIT(5)
+ #define CMN_DTM_WPn_CONFIG_WP_GRP	BIT(4)
+@@ -77,7 +94,11 @@
+ 
+ #define CMN_DTM_PMEVCNTSR		0x240
+ 
++#define CMN_DTM_UNIT_INFO		0x0910
++
+ #define CMN_DTM_NUM_COUNTERS		4
++/* Want more local counters? Why not replicate the whole DTM! Ugh... */
++#define CMN_DTM_OFFSET(n)		((n) * 0x200)
+ 
+ /* The DTC node is where the magic happens */
+ #define CMN_DT_DTC_CTL			0x0a00
+@@ -131,10 +152,10 @@
+ #define CMN_EVENT_NODEID(event)		FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
+ 
+ #define CMN_CONFIG_WP_COMBINE		GENMASK_ULL(27, 24)
+-#define CMN_CONFIG_WP_DEV_SEL		BIT_ULL(48)
+-#define CMN_CONFIG_WP_CHN_SEL		GENMASK_ULL(50, 49)
+-#define CMN_CONFIG_WP_GRP		BIT_ULL(52)
+-#define CMN_CONFIG_WP_EXCLUSIVE		BIT_ULL(53)
++#define CMN_CONFIG_WP_DEV_SEL		GENMASK_ULL(50, 48)
++#define CMN_CONFIG_WP_CHN_SEL		GENMASK_ULL(55, 51)
++#define CMN_CONFIG_WP_GRP		BIT_ULL(56)
++#define CMN_CONFIG_WP_EXCLUSIVE		BIT_ULL(57)
+ #define CMN_CONFIG1_WP_VAL		GENMASK_ULL(63, 0)
+ #define CMN_CONFIG2_WP_MASK		GENMASK_ULL(63, 0)
+ 
+@@ -176,9 +197,12 @@ enum cmn_node_type {
+ 	CMN_TYPE_HNF,
+ 	CMN_TYPE_XP,
+ 	CMN_TYPE_SBSX,
+-	CMN_TYPE_RNI = 0xa,
++	CMN_TYPE_MPAM_S,
++	CMN_TYPE_MPAM_NS,
++	CMN_TYPE_RNI,
+ 	CMN_TYPE_RND = 0xd,
+ 	CMN_TYPE_RNSAM = 0xf,
++	CMN_TYPE_MTSX,
+ 	CMN_TYPE_CXRA = 0x100,
+ 	CMN_TYPE_CXHA = 0x101,
+ 	CMN_TYPE_CXLA = 0x102,
+@@ -233,6 +257,7 @@ struct arm_cmn_dtc {
+ struct arm_cmn {
+ 	struct device *dev;
+ 	void __iomem *base;
++	unsigned int state;
+ 
+ 	enum cmn_revision rev;
+ 	enum cmn_model model;
+@@ -240,6 +265,13 @@ struct arm_cmn {
+ 	u8 mesh_y;
+ 	u16 num_xps;
+ 	u16 num_dns;
++	bool multi_dtm;
++	u8 ports_used;
++	struct {
++		unsigned int rsp_vc_num : 2;
++		unsigned int dat_vc_num : 2;
++	};
++
+ 	struct arm_cmn_node *xps;
+ 	struct arm_cmn_node *dns;
+ 
+@@ -250,7 +282,6 @@ struct arm_cmn {
+ 	int cpu;
+ 	struct hlist_node cpuhp_node;
+ 
+-	unsigned int state;
+ 	struct pmu pmu;
+ };
+ 
+@@ -275,13 +306,25 @@ static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
+ static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
+ {
+ 	struct arm_cmn_nodeid nid;
+-	int bits = arm_cmn_xyidbits(cmn);
+ 
+-	nid.x = CMN_NODEID_X(id, bits);
+-	nid.y = CMN_NODEID_Y(id, bits);
+-	nid.port = CMN_NODEID_PID(id);
+-	nid.dev = CMN_NODEID_DEVID(id);
++	if (cmn->num_xps == 1) {
++		nid.x = 0;
++		nid.y = 0;
++		nid.port = CMN_NODEID_1x1_PID(id);
++		nid.dev = CMN_NODEID_DEVID(id);
++	} else {
++		int bits = arm_cmn_xyidbits(cmn);
+ 
++		nid.x = CMN_NODEID_X(id, bits);
++		nid.y = CMN_NODEID_Y(id, bits);
++		if (cmn->ports_used & 0xc) {
++			nid.port = CMN_NODEID_EXT_PID(id);
++			nid.dev = CMN_NODEID_EXT_DEVID(id);
++		} else {
++			nid.port = CMN_NODEID_PID(id);
++			nid.dev = CMN_NODEID_DEVID(id);
++		}
++	}
+ 	return nid;
+ }
+ 
+@@ -310,6 +353,7 @@ struct arm_cmn_hw_event {
+ 	unsigned int dtc_idx;
+ 	u8 dtcs_used;
+ 	u8 num_dns;
++	u8 dtm_offset;
+ };
+ 
+ #define for_each_hw_dn(hw, dn, i) \
+@@ -354,7 +398,8 @@ struct arm_cmn_format_attr {
+ 		.occupid = _occupid,					\
+ 	}})[0].attr.attr)
+ 
+-static bool arm_cmn_is_occup_event(enum cmn_node_type type, unsigned int id)
++static bool arm_cmn_is_occup_event(enum cmn_model model,
++				   enum cmn_node_type type, unsigned int id)
+ {
+ 	return (type == CMN_TYPE_DVM && id == 0x05) ||
+ 	       (type == CMN_TYPE_HNF && id == 0x0f);
+@@ -375,9 +420,9 @@ static ssize_t arm_cmn_event_show(struct device *dev,
+ 				"type=0x%x,eventid=0x%x,wp_dev_sel=?,wp_chn_sel=?,wp_grp=?,wp_val=?,wp_mask=?\n",
+ 				eattr->type, eattr->eventid);
+ 
+-	if (arm_cmn_is_occup_event(eattr->type, eattr->eventid))
+-		return snprintf(buf, PAGE_SIZE, "type=0x%x,eventid=0x%x,occupid=0x%x\n",
+-				eattr->type, eattr->eventid, eattr->occupid);
++	if (arm_cmn_is_occup_event(eattr->model, eattr->type, eattr->eventid))
++		return sysfs_emit(buf, "type=0x%x,eventid=0x%x,occupid=0x%x\n",
++				  eattr->type, eattr->eventid, eattr->occupid);
+ 
+ 	return snprintf(buf, PAGE_SIZE, "type=0x%x,eventid=0x%x\n",
+ 			eattr->type, eattr->eventid);
+@@ -390,25 +435,36 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
+ 	struct device *dev = kobj_to_dev(kobj);
+ 	struct arm_cmn *cmn = to_cmn(dev_get_drvdata(dev));
+ 	struct arm_cmn_event_attr *eattr;
+-	enum cmn_node_type type;
+ 
+ 	eattr = container_of(attr, typeof(*eattr), attr.attr);
+-	type = eattr->type;
+ 
+ 	if (!(eattr->model & cmn->model))
+ 		return 0;
+ 
+-	/* Watchpoints aren't nodes */
+-	if (type == CMN_TYPE_WP)
+-		type = CMN_TYPE_XP;
++	/* Watchpoints aren't nodes, so avoid confusion */
++	if (eattr->type == CMN_TYPE_WP)
++		return attr->mode;
++
++	/* Hide XP events for unused interfaces/channels */
++	if (eattr->type == CMN_TYPE_XP) {
++		unsigned int intf = (eattr->eventid >> 2) & 7;
++		unsigned int chan = eattr->eventid >> 5;
++
++		if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3)))
++			return 0;
++
++		if ((chan == 5 && cmn->rsp_vc_num < 2) ||
++		    (chan == 6 && cmn->dat_vc_num < 2))
++			return 0;
++	}
+ 
+ 	/* Revision-specific differences */
+ 	if (cmn->model == CMN600 && cmn->rev < CMN600_R1P2) {
+-		if (type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
++		if (eattr->type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
+ 			return 0;
+ 	}
+ 
+-	if (!arm_cmn_node(cmn, type))
++	if (!arm_cmn_node(cmn, eattr->type))
+ 		return 0;
+ 
+ 	return attr->mode;
+@@ -669,7 +725,8 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
+ 	config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
+ 		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
+ 		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
+-		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc);
++		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc) |
++		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
+ 	if (combine && !grp)
+ 		config |= CMN_DTM_WPn_CONFIG_WP_COMBINE;
+ 
+@@ -712,7 +769,7 @@ static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
+ 	offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
+ 	for_each_hw_dn(hw, dn, i) {
+ 		if (dtm != &cmn->dtms[dn->dtm]) {
+-			dtm = &cmn->dtms[dn->dtm];
++			dtm = &cmn->dtms[dn->dtm] + hw->dtm_offset;
+ 			reg = readq_relaxed(dtm->base + offset);
+ 		}
+ 		dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+@@ -800,8 +857,10 @@ static void arm_cmn_event_start(struct perf_event *event, int flags)
+ 		u64 mask = CMN_EVENT_WP_MASK(event);
+ 
+ 		for_each_hw_dn(hw, dn, i) {
+-			writeq_relaxed(val, dn->pmu_base + CMN_DTM_WPn_VAL(wp_idx));
+-			writeq_relaxed(mask, dn->pmu_base + CMN_DTM_WPn_MASK(wp_idx));
++			void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
++
++			writeq_relaxed(val, base + CMN_DTM_WPn_VAL(wp_idx));
++			writeq_relaxed(mask, base + CMN_DTM_WPn_MASK(wp_idx));
+ 		}
+ 	} else for_each_hw_dn(hw, dn, i) {
+ 		int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+@@ -826,8 +885,10 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
+ 		int wp_idx = arm_cmn_wp_idx(event);
+ 
+ 		for_each_hw_dn(hw, dn, i) {
+-			writeq_relaxed(0, dn->pmu_base + CMN_DTM_WPn_MASK(wp_idx));
+-			writeq_relaxed(~0ULL, dn->pmu_base + CMN_DTM_WPn_VAL(wp_idx));
++			void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
++
++			writeq_relaxed(0, base + CMN_DTM_WPn_MASK(wp_idx));
++			writeq_relaxed(~0ULL, base + CMN_DTM_WPn_VAL(wp_idx));
+ 		}
+ 	} else for_each_hw_dn(hw, dn, i) {
+ 		int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+@@ -847,7 +908,8 @@ struct arm_cmn_val {
+ 	bool cycles;
+ };
+ 
+-static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *event)
++static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
++				  struct perf_event *event)
+ {
+ 	struct arm_cmn_hw_event *hw = to_cmn_hw(event);
+ 	struct arm_cmn_node *dn;
+@@ -865,7 +927,7 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
+ 	}
+ 
+ 	val->dtc_count++;
+-	if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
++	if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
+ 		occupid = CMN_EVENT_OCCUPID(event) + 1;
+ 	else
+ 		occupid = 0;
+@@ -884,7 +946,7 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
+ 	}
+ }
+ 
+-static int arm_cmn_validate_group(struct perf_event *event)
++static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
+ {
+ 	struct arm_cmn_hw_event *hw = to_cmn_hw(event);
+ 	struct arm_cmn_node *dn;
+@@ -904,9 +966,9 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 	if (!val)
+ 		return -ENOMEM;
+ 
+-	arm_cmn_val_add_event(val, leader);
++	arm_cmn_val_add_event(cmn, val, leader);
+ 	for_each_sibling_event(sibling, leader)
+-		arm_cmn_val_add_event(val, sibling);
++		arm_cmn_val_add_event(cmn, val, sibling);
+ 
+ 	type = CMN_EVENT_TYPE(event);
+ 	if (type == CMN_TYPE_DTC) {
+@@ -917,7 +979,7 @@ static int arm_cmn_validate_group(struct perf_event *event)
+ 	if (val->dtc_count == CMN_DT_NUM_COUNTERS)
+ 		goto done;
+ 
+-	if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
++	if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
+ 		occupid = CMN_EVENT_OCCUPID(event) + 1;
+ 	else
+ 		occupid = 0;
+@@ -980,6 +1042,9 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 		eventid = CMN_EVENT_EVENTID(event);
+ 		if (eventid != CMN_WP_UP && eventid != CMN_WP_DOWN)
+ 			return -EINVAL;
++		/* ...but the DTM may depend on which port we're watching */
++		if (cmn->multi_dtm)
++			hw->dtm_offset = CMN_EVENT_WP_DEV_SEL(event) / 2;
+ 	}
+ 
+ 	bynodeid = CMN_EVENT_BYNODEID(event);
+@@ -1007,7 +1072,7 @@ static int arm_cmn_event_init(struct perf_event *event)
+ 		return -EINVAL;
+ 	}
+ 
+-	return arm_cmn_validate_group(event);
++	return arm_cmn_validate_group(cmn, event);
+ }
+ 
+ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
+@@ -1017,13 +1082,13 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
+ 	enum cmn_node_type type = CMN_EVENT_TYPE(event);
+ 
+ 	while (i--) {
+-		struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm];
++		struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm] + hw->dtm_offset;
+ 		unsigned int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+ 
+ 		if (type == CMN_TYPE_WP)
+ 			dtm->wp_event[arm_cmn_wp_idx(event)] = -1;
+ 
+-		if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
++		if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
+ 			hw->dn[i].occupid_count--;
+ 
+ 		dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
+@@ -1069,7 +1134,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 
+ 	/* ...then the local counters to feed it. */
+ 	for_each_hw_dn(hw, dn, i) {
+-		struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
++		struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm] + hw->dtm_offset;
+ 		unsigned int dtm_idx, shift;
+ 		u64 reg;
+ 
+@@ -1098,10 +1163,13 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
+ 		} else {
+ 			struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ 
++			if (cmn->multi_dtm)
++				nid.port %= 2;
++
+ 			input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
+ 				    (nid.port << 4) + (nid.dev << 2);
+ 
+-			if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
++			if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event))) {
+ 				u8 occupid = CMN_EVENT_OCCUPID(event);
+ 
+ 				if (dn->occupid_count == 0) {
+@@ -1283,11 +1351,11 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
+ 	return 0;
+ }
+ 
+-static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp)
++static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp, int idx)
+ {
+ 	int i;
+ 
+-	dtm->base = xp->pmu_base;
++	dtm->base = xp->pmu_base + CMN_DTM_OFFSET(idx);
+ 	dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
+ 	for (i = 0; i < 4; i++) {
+ 		dtm->wp_event[i] = -1;
+@@ -1345,6 +1413,8 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
+ 
+ 		xp = arm_cmn_node_to_xp(cmn, dn);
+ 		dn->dtm = xp->dtm;
++		if (cmn->multi_dtm)
++			dn->dtm += arm_cmn_nid(cmn, dn->id).port / 2;
+ 
+ 		if (dn->type == CMN_TYPE_DTC) {
+ 			int err;
+@@ -1408,6 +1478,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
+ 	cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
+ 
++	reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL);
++	cmn->multi_dtm = reg & CMN_INFO_MULTIPLE_DTM_EN;
++	cmn->rsp_vc_num = FIELD_GET(CMN_INFO_RSP_VC_NUM, reg);
++	cmn->dat_vc_num = FIELD_GET(CMN_INFO_DAT_VC_NUM, reg);
++
+ 	reg = readq_relaxed(cfg_region + CMN_CHILD_INFO);
+ 	child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
+ 	child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
+@@ -1429,7 +1504,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	if (!dn)
+ 		return -ENOMEM;
+ 
+-	dtm = devm_kcalloc(cmn->dev, cmn->num_xps, sizeof(*dtm), GFP_KERNEL);
++	/* Initial safe upper bound on DTMs for any possible mesh layout */
++	i = cmn->num_xps;
++	if (cmn->multi_dtm)
++		i += cmn->num_xps + 1;
++	dtm = devm_kcalloc(cmn->dev, i, sizeof(*dtm), GFP_KERNEL);
+ 	if (!dtm)
+ 		return -ENOMEM;
+ 
+@@ -1439,6 +1518,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	for (i = 0; i < cmn->num_xps; i++) {
+ 		void __iomem *xp_region = cmn->base + xp_offset[i];
+ 		struct arm_cmn_node *xp = dn++;
++		unsigned int xp_ports = 0;
+ 
+ 		arm_cmn_init_node_info(cmn, xp_offset[i], xp);
+ 		/*
+@@ -1450,9 +1530,39 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		if (xp->id == (1 << 3))
+ 			cmn->mesh_x = xp->logid;
+ 
+-		xp->dtc = 0xf;
++		if (cmn->model == CMN600)
++			xp->dtc = 0xf;
++		else
++			xp->dtc = 1 << readl_relaxed(xp_region + CMN_DTM_UNIT_INFO);
++
+ 		xp->dtm = dtm - cmn->dtms;
+-		arm_cmn_init_dtm(dtm++, xp);
++		arm_cmn_init_dtm(dtm++, xp, 0);
++		/*
++		 * Keeping track of connected ports will let us filter out
++		 * unnecessary XP events easily. We can also reliably infer the
++		 * "extra device ports" configuration for the node ID format
++		 * from this, since in that case we will see at least one XP
++		 * with port 2 connected, for the HN-D.
++		 */
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P0))
++			xp_ports |= BIT(0);
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P1))
++			xp_ports |= BIT(1);
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P2))
++			xp_ports |= BIT(2);
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P3))
++			xp_ports |= BIT(3);
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P4))
++			xp_ports |= BIT(4);
++		if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P5))
++			xp_ports |= BIT(5);
++
++		if (cmn->multi_dtm && (xp_ports & 0xc))
++			arm_cmn_init_dtm(dtm++, xp, 1);
++		if (cmn->multi_dtm && (xp_ports & 0x30))
++			arm_cmn_init_dtm(dtm++, xp, 2);
++
++		cmn->ports_used |= xp_ports;
+ 
+ 		reg = readq_relaxed(xp_region + CMN_CHILD_INFO);
+ 		child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
+@@ -1488,11 +1598,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 			case CMN_TYPE_SBSX:
+ 			case CMN_TYPE_RNI:
+ 			case CMN_TYPE_RND:
++			case CMN_TYPE_MTSX:
+ 			case CMN_TYPE_CXRA:
+ 			case CMN_TYPE_CXHA:
+ 				dn++;
+ 				break;
+ 			/* Nothing to see here */
++			case CMN_TYPE_MPAM_S:
++			case CMN_TYPE_MPAM_NS:
+ 			case CMN_TYPE_RNSAM:
+ 			case CMN_TYPE_CXLA:
+ 				break;
+@@ -1512,6 +1625,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 	if (dn)
+ 		cmn->dns = dn;
+ 
++	sz = (void *)dtm - (void *)cmn->dtms;
++	dtm = devm_krealloc(cmn->dev, cmn->dtms, sz, GFP_KERNEL);
++	if (dtm)
++		cmn->dtms = dtm;
++
+ 	/*
+ 	 * If mesh_x wasn't set during discovery then we never saw
+ 	 * an XP at (0,1), thus we must have an Nx1 configuration.
+@@ -1520,9 +1638,15 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
+ 		cmn->mesh_x = cmn->num_xps;
+ 	cmn->mesh_y = cmn->num_xps / cmn->mesh_x;
+ 
++	/* 1x1 config plays havoc with XP event encodings */
++	if (cmn->num_xps == 1)
++		dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events manually\n");
++
+ 	dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev);
+-	dev_dbg(cmn->dev, "mesh %dx%d, ID width %d\n",
+-		cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn));
++	reg = cmn->ports_used;
++	dev_dbg(cmn->dev, "mesh %dx%d, ID width %d, ports %6pbl%s\n",
++		cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn), &reg,
++		cmn->multi_dtm ? ", multi-DTM" : "");
+ 
+ 	return 0;
+ }
+-- 
+2.25.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
new file mode 100644
index 0000000..a12911a
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
@@ -0,0 +1,150 @@ 
+From f5d0979c2385c3ef43d6f2af07c14ee897835e2c Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 3 Dec 2021 11:45:02 +0000
+Subject: [PATCH 14/14] perf/arm-cmn: Add CI-700 Support
+
+Add the identifiers and events for the CI-700 coherent interconnect.
+
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+
+Upstream-Status: Backport [https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com]
+Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+---
+ drivers/perf/arm-cmn.c | 57 +++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 53 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
+index 871c86687379..e0f78b6c643c 100644
+--- a/drivers/perf/arm-cmn.c
++++ b/drivers/perf/arm-cmn.c
+@@ -175,6 +175,7 @@
+ enum cmn_model {
+ 	CMN_ANY = -1,
+ 	CMN600 = 1,
++	CI700 = 2,
+ };
+ 
+ /* CMN-600 r0px shouldn't exist in silicon, thankfully */
+@@ -186,6 +187,9 @@ enum cmn_revision {
+ 	CMN600_R2P0,
+ 	CMN600_R3P0,
+ 	CMN600_R3P1,
++	CI700_R0P0 = 0,
++	CI700_R1P0,
++	CI700_R2P0,
+ };
+ 
+ enum cmn_node_type {
+@@ -401,8 +405,10 @@ struct arm_cmn_format_attr {
+ static bool arm_cmn_is_occup_event(enum cmn_model model,
+ 				   enum cmn_node_type type, unsigned int id)
+ {
+-	return (type == CMN_TYPE_DVM && id == 0x05) ||
+-	       (type == CMN_TYPE_HNF && id == 0x0f);
++	if (type == CMN_TYPE_DVM)
++		return (model == CMN600 && id == 0x05) ||
++		       (model == CI700 && id == 0x0c);
++	return type == CMN_TYPE_HNF && id == 0x0f;
+ }
+ 
+ static ssize_t arm_cmn_event_show(struct device *dev,
+@@ -497,14 +503,19 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
+ 	__CMN_EVENT_XP(n_##_name, (_event) | (2 << 2)),		\
+ 	__CMN_EVENT_XP(s_##_name, (_event) | (3 << 2)),		\
+ 	__CMN_EVENT_XP(p0_##_name, (_event) | (4 << 2)),	\
+-	__CMN_EVENT_XP(p1_##_name, (_event) | (5 << 2))
++	__CMN_EVENT_XP(p1_##_name, (_event) | (5 << 2)),	\
++	__CMN_EVENT_XP(p2_##_name, (_event) | (6 << 2)),	\
++	__CMN_EVENT_XP(p3_##_name, (_event) | (7 << 2))
+ 
+ /* Good thing there are only 3 fundamental XP events... */
+ #define CMN_EVENT_XP(_name, _event)				\
+ 	_CMN_EVENT_XP(req_##_name, (_event) | (0 << 5)),	\
+ 	_CMN_EVENT_XP(rsp_##_name, (_event) | (1 << 5)),	\
+ 	_CMN_EVENT_XP(snp_##_name, (_event) | (2 << 5)),	\
+-	_CMN_EVENT_XP(dat_##_name, (_event) | (3 << 5))
++	_CMN_EVENT_XP(dat_##_name, (_event) | (3 << 5)),	\
++	_CMN_EVENT_XP(pub_##_name, (_event) | (4 << 5)),	\
++	_CMN_EVENT_XP(rsp2_##_name, (_event) | (5 << 5)),	\
++	_CMN_EVENT_XP(dat2_##_name, (_event) | (6 << 5))
+ 
+ 
+ static struct attribute *arm_cmn_event_attrs[] = {
+@@ -522,6 +533,20 @@ static struct attribute *arm_cmn_event_attrs[] = {
+ 	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_all, 0x05, 0),
+ 	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmop, 0x05, 1),
+ 	_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmsync, 0x05, 2),
++	CMN_EVENT_DVM(CI700, dvmop_tlbi,		0x01),
++	CMN_EVENT_DVM(CI700, dvmop_bpi,			0x02),
++	CMN_EVENT_DVM(CI700, dvmop_pici,		0x03),
++	CMN_EVENT_DVM(CI700, dvmop_vici,		0x04),
++	CMN_EVENT_DVM(CI700, dvmsync,			0x05),
++	CMN_EVENT_DVM(CI700, vmid_filtered,		0x06),
++	CMN_EVENT_DVM(CI700, rndop_filtered,		0x07),
++	CMN_EVENT_DVM(CI700, retry,			0x08),
++	CMN_EVENT_DVM(CI700, txsnp_flitv,		0x09),
++	CMN_EVENT_DVM(CI700, txsnp_stall,		0x0a),
++	CMN_EVENT_DVM(CI700, trkfull,			0x0b),
++	_CMN_EVENT_DVM(CI700, trk_occupancy_all,	0x0c, 0),
++	_CMN_EVENT_DVM(CI700, trk_occupancy_dvmop,	0x0c, 1),
++	_CMN_EVENT_DVM(CI700, trk_occupancy_dvmsync,	0x0c, 2),
+ 
+ 	CMN_EVENT_HNF(CMN_ANY, cache_miss,		0x01),
+ 	CMN_EVENT_HNF(CMN_ANY, slc_sf_cache_access,	0x02),
+@@ -558,6 +583,9 @@ static struct attribute *arm_cmn_event_attrs[] = {
+ 	CMN_EVENT_HNF(CMN_ANY, stash_snp_sent,		0x1d),
+ 	CMN_EVENT_HNF(CMN_ANY, stash_data_pull,		0x1e),
+ 	CMN_EVENT_HNF(CMN_ANY, snp_fwded,		0x1f),
++	CMN_EVENT_HNF(CI700, atomic_fwd,		0x20),
++	CMN_EVENT_HNF(CI700, mpam_hardlim,		0x21),
++	CMN_EVENT_HNF(CI700, mpam_softlim,		0x22),
+ 
+ 	CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl,		0x20),
+ 	CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl,		0x21),
+@@ -598,6 +626,7 @@ static struct attribute *arm_cmn_event_attrs[] = {
+ 	CMN_EVENT_SBSX(CMN_ANY, wdb_occ_cnt_ovfl,	0x14),
+ 	CMN_EVENT_SBSX(CMN_ANY, rd_axi_trkr_occ_cnt_ovfl, 0x15),
+ 	CMN_EVENT_SBSX(CMN_ANY, cmo_axi_trkr_occ_cnt_ovfl, 0x16),
++	CMN_EVENT_SBSX(CI700, rdb_occ_cnt_ovfl,		0x17),
+ 	CMN_EVENT_SBSX(CMN_ANY, arvalid_no_arready,	0x21),
+ 	CMN_EVENT_SBSX(CMN_ANY, awvalid_no_awready,	0x22),
+ 	CMN_EVENT_SBSX(CMN_ANY, wvalid_no_wready,	0x23),
+@@ -624,6 +653,25 @@ static struct attribute *arm_cmn_event_attrs[] = {
+ 	CMN_EVENT_RNID(CMN600, rdb_replay,		0x12),
+ 	CMN_EVENT_RNID(CMN600, rdb_hybrid,		0x13),
+ 	CMN_EVENT_RNID(CMN600, rdb_ord,			0x14),
++	CMN_EVENT_RNID(CI700, padb_occ_ovfl,		0x11),
++	CMN_EVENT_RNID(CI700, rpdb_occ_ovfl,		0x12),
++	CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice1,	0x13),
++	CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice2,	0x14),
++	CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice3,	0x15),
++	CMN_EVENT_RNID(CI700, wrt_throttled,		0x16),
++
++	CMN_EVENT_MTSX(tc_lookup,			0x01),
++	CMN_EVENT_MTSX(tc_fill,				0x02),
++	CMN_EVENT_MTSX(tc_miss,				0x03),
++	CMN_EVENT_MTSX(tdb_forward,			0x04),
++	CMN_EVENT_MTSX(tcq_hazard,			0x05),
++	CMN_EVENT_MTSX(tcq_rd_alloc,			0x06),
++	CMN_EVENT_MTSX(tcq_wr_alloc,			0x07),
++	CMN_EVENT_MTSX(tcq_cmo_alloc,			0x08),
++	CMN_EVENT_MTSX(axi_rd_req,			0x09),
++	CMN_EVENT_MTSX(axi_wr_req,			0x0a),
++	CMN_EVENT_MTSX(tcq_occ_cnt_ovfl,		0x0b),
++	CMN_EVENT_MTSX(tdb_occ_cnt_ovfl,		0x0c),
+ 
+ 	NULL
+ };
+@@ -1773,6 +1821,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
+ #ifdef CONFIG_OF
+ static const struct of_device_id arm_cmn_of_match[] = {
+ 	{ .compatible = "arm,cmn-600", .data = (void *)CMN600 },
++	{ .compatible = "arm,ci-700", .data = (void *)CI700 },
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
+-- 
+2.25.1
+
diff --git a/tatus b/tatus
new file mode 100644
index 0000000..b86e09b
--- /dev/null
+++ b/tatus
@@ -0,0 +1,168 @@ 
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
+index 0defb4f..e8674c3 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch
+@@ -25,6 +25,7 @@ Link: https://lore.kernel.org/r/20210518093118.277228577@linutronix.de
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/20210518093118.277228577@linutronix.de]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 9 ++-------
+  1 file changed, 2 insertions(+), 7 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
+index 66c0582..e06fb88 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch
+@@ -13,6 +13,7 @@ Fixes: 0ba64770a2f2 ("perf: Add Arm CMN-600 PMU driver")
+ Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/2c221d745544774e4b07583b65b5d4d94f7e0fe4.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 5 +++--
+  1 file changed, 3 insertions(+), 2 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
+index 2a1bbde..f93bff7 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 51 +++++++++++++++++++++++++++++++-----------
+  1 file changed, 38 insertions(+), 13 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
+index 47b24e9..1a3e2d9 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/Kconfig   |  2 +-
+  drivers/perf/arm-cmn.c | 25 +++++++++++++------------
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
+index 80fbc06..ce4c2e5 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 94 +++++++++++++++++++++++++-----------------
+  1 file changed, 56 insertions(+), 38 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
+index 7b86023..fbe49b2 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 33 ++++++++++++++++++++-------------
+  1 file changed, 20 insertions(+), 13 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
+index d01ff04..3b11192 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch
+@@ -11,6 +11,7 @@ Signed-off-by: Junhao He <hejunhao2@hisilicon.com>
+ Signed-off-by: Jay Fang <f.fangjian@huawei.com>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/all/1620736054-58412-4-git-send-email-f.fangjian@huawei.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 2 +-
+  1 file changed, 1 insertion(+), 1 deletion(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
+index 3a37287..6a68a79 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch
+@@ -12,6 +12,7 @@ Link: https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 169 +++++++++++++++++++++--------------------
+  1 file changed, 87 insertions(+), 82 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
+index 3be9719..af33468 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch
+@@ -14,6 +14,7 @@ Link: https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 17 +++++++++--------
+  1 file changed, 9 insertions(+), 8 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
+index af44f5b..56334e8 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch
+@@ -17,6 +17,7 @@ Link: https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 29 ++++++++++++-----------------
+  1 file changed, 12 insertions(+), 17 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
+index 90a67a8..06adc56 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 43 ++++++++++++++++++++++++------------------
+  1 file changed, 25 insertions(+), 18 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
+index 14c95c4..0fbc5cb 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch
+@@ -15,6 +15,7 @@ Link: https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 313 +++++++++++++++++++++--------------------
+  1 file changed, 162 insertions(+), 151 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
+index ababdcd..fa0c5d9 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch
+@@ -13,6 +13,7 @@ it around as necessary, and handling (most of) the new choices.
+ Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+ Link: https://lore.kernel.org/r/e58b495bcc7deec3882be4bac910ed0bf6979674.1638530442.git.robin.murphy@arm.com
+ Signed-off-by: Will Deacon <will@kernel.org>
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 222 ++++++++++++++++++++++++++++++++---------
+  1 file changed, 173 insertions(+), 49 deletions(-)
+diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
+index 4be16ae..a12911a 100644
+--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
++++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch
+@@ -10,6 +10,7 @@ Link: https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530
+ Signed-off-by: Will Deacon <will@kernel.org>
+ 
+ Upstream-Status: Backport [https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com]
++Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
+ ---
+  drivers/perf/arm-cmn.c | 57 +++++++++++++++++++++++++++++++++++++++---
+  1 file changed, 53 insertions(+), 4 deletions(-)