blob: 2fd7ba4c93ee814b4715844931ecf1e74e3c75d8 [file] [log] [blame]
Patrick Williams2194f502022-10-16 14:26:09 -05001From ca15b67dc746c13a8231d11a3e2925f128982a7d Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Robin Murphy <robin.murphy@arm.com>
3Date: Fri, 3 Dec 2021 11:44:54 +0000
Patrick Williams2194f502022-10-16 14:26:09 -05004Subject: [PATCH 19/40] perf/arm-cmn: Streamline node iteration
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
6Refactor the places where we scan through the set of nodes to switch
7from explicit array indexing to pointer-based iteration. This leads to
8slightly simpler object code, but also makes the source less dense and
9more pleasant for further development. It also unearths an almost-bug
10in arm_cmn_event_init() where we've been depending on the "array index"
11of NULL relative to cmn->dns being a sufficiently large number, yuck.
12
13Signed-off-by: Robin Murphy <robin.murphy@arm.com>
14Link: https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com
15Signed-off-by: Will Deacon <will@kernel.org>
16
17Upstream-Status: Backport [https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com]
18Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
19---
20 drivers/perf/arm-cmn.c | 33 ++++++++++++++++++++-------------
21 1 file changed, 20 insertions(+), 13 deletions(-)
22
23diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
Patrick Williams2194f502022-10-16 14:26:09 -050024index adf50d613734..da7bf779fec2 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040025--- a/drivers/perf/arm-cmn.c
26+++ b/drivers/perf/arm-cmn.c
27@@ -299,11 +299,11 @@ static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
28 static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
29 enum cmn_node_type type)
30 {
31- int i;
32+ struct arm_cmn_node *dn;
33
34- for (i = 0; i < cmn->num_dns; i++)
35- if (cmn->dns[i].type == type)
36- return &cmn->dns[i];
37+ for (dn = cmn->dns; dn->type; dn++)
38+ if (dn->type == type)
39+ return dn;
40 return NULL;
41 }
42
43@@ -941,8 +941,8 @@ static int arm_cmn_event_init(struct perf_event *event)
44 {
45 struct arm_cmn *cmn = to_cmn(event->pmu);
46 struct arm_cmn_hw_event *hw = to_cmn_hw(event);
47+ struct arm_cmn_node *dn;
48 enum cmn_node_type type;
49- unsigned int i;
50 bool bynodeid;
51 u16 nodeid, eventid;
52
53@@ -974,10 +974,12 @@ static int arm_cmn_event_init(struct perf_event *event)
54 nodeid = CMN_EVENT_NODEID(event);
55
56 hw->dn = arm_cmn_node(cmn, type);
57- for (i = hw->dn - cmn->dns; i < cmn->num_dns && cmn->dns[i].type == type; i++) {
58+ if (!hw->dn)
59+ return -EINVAL;
60+ for (dn = hw->dn; dn->type == type; dn++) {
61 if (!bynodeid) {
62 hw->num_dns++;
63- } else if (cmn->dns[i].id != nodeid) {
64+ } else if (dn->id != nodeid) {
65 hw->dn++;
66 } else {
67 hw->num_dns = 1;
68@@ -1332,7 +1334,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
69
70 cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
71
72- for (dn = cmn->dns; dn < cmn->dns + cmn->num_dns; dn++) {
73+ for (dn = cmn->dns; dn->type; dn++) {
74 if (dn->type != CMN_TYPE_XP)
75 arm_cmn_init_node_to_xp(cmn, dn);
76 else if (cmn->num_dtcs == 1)
77@@ -1382,6 +1384,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
78 u32 xp_offset[CMN_MAX_XPS];
79 u64 reg;
80 int i, j;
81+ size_t sz;
82
83 cfg_region = cmn->base + rgn_offset;
84 reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
85@@ -1408,14 +1411,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
86 cmn->num_dns += FIELD_GET(CMN_CI_CHILD_COUNT, reg);
87 }
88
89- /* Cheeky +1 to help terminate pointer-based iteration */
90- cmn->dns = devm_kcalloc(cmn->dev, cmn->num_dns + 1,
91- sizeof(*cmn->dns), GFP_KERNEL);
92- if (!cmn->dns)
93+ /* Cheeky +1 to help terminate pointer-based iteration later */
94+ dn = devm_kcalloc(cmn->dev, cmn->num_dns + 1, sizeof(*dn), GFP_KERNEL);
95+ if (!dn)
96 return -ENOMEM;
97
98 /* Pass 2: now we can actually populate the nodes */
99- dn = cmn->dns;
100+ cmn->dns = dn;
101 for (i = 0; i < cmn->num_xps; i++) {
102 void __iomem *xp_region = cmn->base + xp_offset[i];
103 struct arm_cmn_node *xp = dn++;
104@@ -1484,6 +1486,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
105 /* Correct for any nodes we skipped */
106 cmn->num_dns = dn - cmn->dns;
107
108+ sz = (void *)(dn + 1) - (void *)cmn->dns;
109+ dn = devm_krealloc(cmn->dev, cmn->dns, sz, GFP_KERNEL);
110+ if (dn)
111+ cmn->dns = dn;
112+
113 /*
114 * If mesh_x wasn't set during discovery then we never saw
115 * an XP at (0,1), thus we must have an Nx1 configuration.
116--
Patrick Williams2194f502022-10-16 14:26:09 -05001172.34.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400118