new file mode 100644
@@ -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
+
@@ -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 \
"
@@ -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
new file mode 100644
@@ -0,0 +1 @@
+CONFIG_ARM_CMN=y
@@ -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"
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -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), ®,
++ cmn->multi_dtm ? ", multi-DTM" : "");
+
+ return 0;
+ }
+--
+2.25.1
+
new file mode 100644
@@ -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
+
new file mode 100644
@@ -0,0 +1,168 @@
+[1mdiff --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[m
+[1mindex 0defb4f..e8674c3 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0024-perf-arm-cmn-Use-irq_set_affinity.patch[m
+[36m@@ -25,6 +25,7 @@[m [mLink: https://lore.kernel.org/r/20210518093118.277228577@linutronix.de[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/20210518093118.277228577@linutronix.de][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 9 ++-------[m
+ 1 file changed, 2 insertions(+), 7 deletions(-)[m
+[1mdiff --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[m
+[1mindex 66c0582..e06fb88 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0025-perf-arm-cmn-Fix-CPU-hotplug-unregistration.patch[m
+[36m@@ -13,6 +13,7 @@[m [mFixes: 0ba64770a2f2 ("perf: Add Arm CMN-600 PMU driver")[m
+ Signed-off-by: Robin Murphy <robin.murphy@arm.com>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/2c221d745544774e4b07583b65b5d4d94f7e0fe4.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 5 +++--[m
+ 1 file changed, 3 insertions(+), 2 deletions(-)[m
+[1mdiff --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[m
+[1mindex 2a1bbde..f93bff7 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0026-perf-arm-cmn-Account-for-NUMA-affinity.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 51 +++++++++++++++++++++++++++++++-----------[m
+ 1 file changed, 38 insertions(+), 13 deletions(-)[m
+[1mdiff --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[m
+[1mindex 47b24e9..1a3e2d9 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0027-perf-arm-cmn-Drop-compile-test-restriction.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/Kconfig | 2 +-[m
+ drivers/perf/arm-cmn.c | 25 +++++++++++++------------[m
+[1mdiff --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[m
+[1mindex 80fbc06..ce4c2e5 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0028-perf-arm-cmn-Refactor-node-ID-handling.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 94 +++++++++++++++++++++++++-----------------[m
+ 1 file changed, 56 insertions(+), 38 deletions(-)[m
+[1mdiff --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[m
+[1mindex 7b86023..fbe49b2 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0029-perf-arm-cmn-Streamline-node-iteration.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 33 ++++++++++++++++++++-------------[m
+ 1 file changed, 20 insertions(+), 13 deletions(-)[m
+[1mdiff --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[m
+[1mindex d01ff04..3b11192 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0030-drivers-perf-arm-cmn-Add-space-after.patch[m
+[36m@@ -11,6 +11,7 @@[m [mSigned-off-by: Junhao He <hejunhao2@hisilicon.com>[m
+ Signed-off-by: Jay Fang <f.fangjian@huawei.com>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/all/1620736054-58412-4-git-send-email-f.fangjian@huawei.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 2 +-[m
+ 1 file changed, 1 insertion(+), 1 deletion(-)[m
+[1mdiff --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[m
+[1mindex 3a37287..6a68a79 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0031-perf-arm-cmn-Refactor-DTM-handling.patch[m
+[36m@@ -12,6 +12,7 @@[m [mLink: https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 169 +++++++++++++++++++++--------------------[m
+ 1 file changed, 87 insertions(+), 82 deletions(-)[m
+[1mdiff --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[m
+[1mindex 3be9719..af33468 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0032-perf-arm-cmn-Optimise-DTM-counter-reads.patch[m
+[36m@@ -14,6 +14,7 @@[m [mLink: https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 17 +++++++++--------[m
+ 1 file changed, 9 insertions(+), 8 deletions(-)[m
+[1mdiff --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[m
+[1mindex af44f5b..56334e8 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0033-perf-arm-cmn-Optimise-DTC-counter-accesses.patch[m
+[36m@@ -17,6 +17,7 @@[m [mLink: https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 29 ++++++++++++-----------------[m
+ 1 file changed, 12 insertions(+), 17 deletions(-)[m
+[1mdiff --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[m
+[1mindex 90a67a8..06adc56 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0034-perf-arm-cmn-Move-group-validation-data-off-stack.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 43 ++++++++++++++++++++++++------------------[m
+ 1 file changed, 25 insertions(+), 18 deletions(-)[m
+[1mdiff --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[m
+[1mindex 14c95c4..0fbc5cb 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0035-perf-arm-cmn-Demarcate-CMN-600-specifics.patch[m
+[36m@@ -15,6 +15,7 @@[m [mLink: https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 313 +++++++++++++++++++++--------------------[m
+ 1 file changed, 162 insertions(+), 151 deletions(-)[m
+[1mdiff --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[m
+[1mindex ababdcd..fa0c5d9 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0036-perf-arm-cmn-Support-new-IP-features.patch[m
+[36m@@ -13,6 +13,7 @@[m [mit around as necessary, and handling (most of) the new choices.[m
+ Signed-off-by: Robin Murphy <robin.murphy@arm.com>[m
+ Link: https://lore.kernel.org/r/e58b495bcc7deec3882be4bac910ed0bf6979674.1638530442.git.robin.murphy@arm.com[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 222 ++++++++++++++++++++++++++++++++---------[m
+ 1 file changed, 173 insertions(+), 49 deletions(-)[m
+[1mdiff --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[m
+[1mindex 4be16ae..a12911a 100644[m
+[1m--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch[m
+[1m+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc/0037-perf-arm-cmn-Add-CI-700-Support.patch[m
+[36m@@ -10,6 +10,7 @@[m [mLink: https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530[m
+ Signed-off-by: Will Deacon <will@kernel.org>[m
+ [m
+ Upstream-Status: Backport [https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com][m
+[32m+[m[32mSigned-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>[m
+ ---[m
+ drivers/perf/arm-cmn.c | 57 +++++++++++++++++++++++++++++++++++++++---[m
+ 1 file changed, 53 insertions(+), 4 deletions(-)[m
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