From: Kathiravan Thirumoorthy <kathiravan.thirumoorthy@oss.qualcomm.com>
To: Georgi Djakov <djakov@kernel.org>,
Bjorn Andersson <andersson@kernel.org>,
Abel Vesa <abelvesa@kernel.org>, Stephen Boyd <sboyd@kernel.org>,
Brian Masney <bmasney+clk@redhat.com>,
Jerome Brunet <jbrunet+clk@baylibre.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>
Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm@vger.kernel.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org,
Kathiravan Thirumoorthy
<kathiravan.thirumoorthy@oss.qualcomm.com>
Subject: [PATCH 1/4] interconnect: icc-clk: support N:1 master-to-slave topology
Date: Wed, 07 Oct 2026 12:20:44 +0530 [thread overview]
Message-ID: <20261007-ipq9650_apss_clk-v1-1-fd4c2b3cbdea@oss.qualcomm.com> (raw)
In-Reply-To: <20261007-ipq9650_apss_clk-v1-0-fd4c2b3cbdea@oss.qualcomm.com>
icc_clk_register() assumes each icc_clk_data entry describes a unique
master/slave pair and creates both nodes for every entry. When several
masters share the same slave_id, the shared slave node is created and
added again on each later entry. icc_node_create() returns the existing
node, so icc_node_add() hits WARN_ON(node->provider):
WARNING: drivers/interconnect/core.c:1103 at icc_node_add+0x10c/0x120
Call trace:
icc_node_add+0x10c/0x120 (P)
icc_clk_register+0x1a4/0x214
devm_icc_clk_register+0x18/0x80
qcom_cc_really_probe+0x4c8/0x514
apss_ipq9650_probe+0xc0/0x108
This topology is needed on IPQ9650, where the silver and gold CPU
clusters both vote on the single L3 clock through a shared SLAVE_L3
node.
The onecell table is also filled in registration order, so xlate only
works when the node IDs happen to match that order. Size the table by
the highest node ID, index it by ID, and skip slave creation when the
node is already registered.
icc_clk_set() also passes only the requesting node's bandwidth to
clk_set_rate(), so the last writer wins. A low vote from one master can
then lower the clock below what another master asked for. Before setting
the rate, take the highest peak bandwidth across all nodes that share
the clock.
Signed-off-by: Kathiravan Thirumoorthy <kathiravan.thirumoorthy@oss.qualcomm.com>
---
drivers/interconnect/icc-clk.c | 45 +++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 7 deletions(-)
diff --git a/drivers/interconnect/icc-clk.c b/drivers/interconnect/icc-clk.c
index 93c030608d3e..567d071fade8 100644
--- a/drivers/interconnect/icc-clk.c
+++ b/drivers/interconnect/icc-clk.c
@@ -24,7 +24,10 @@ struct icc_clk_provider {
static int icc_clk_set(struct icc_node *src, struct icc_node *dst)
{
+ unsigned long rate = icc_units_to_bps(src->peak_bw);
+ struct icc_provider *provider = src->provider;
struct icc_clk_node *qn = src->data;
+ struct icc_node *node;
int ret;
if (!qn || !qn->clk)
@@ -45,7 +48,21 @@ static int icc_clk_set(struct icc_node *src, struct icc_node *dst)
qn->enabled = true;
}
- return clk_set_rate(qn->clk, icc_units_to_bps(src->peak_bw));
+ /*
+ * Multiple master nodes can share the same underlying clock (N:1
+ * topology, e.g. several CPU clusters voting on one L3 clock).
+ * Aggregate the peak bandwidth across all of them before setting
+ * the rate, otherwise the last caller wins and can undervote what
+ * another master already asked for.
+ */
+ list_for_each_entry(node, &provider->nodes, node_list) {
+ struct icc_clk_node *n = node->data;
+
+ if (n && clk_is_match(n->clk, qn->clk))
+ rate = max(rate, icc_units_to_bps(node->peak_bw));
+ }
+
+ return clk_set_rate(qn->clk, rate);
}
static int icc_clk_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
@@ -82,12 +99,17 @@ struct icc_provider *icc_clk_register(struct device *dev,
struct icc_provider *provider;
struct icc_onecell_data *onecell;
struct icc_node *node;
- int ret, i, j;
+ unsigned int max_id = 0;
+ int ret, i;
- onecell = devm_kzalloc(dev, struct_size(onecell, nodes, 2 * num_clocks), GFP_KERNEL);
+ /* Find the highest node ID to size the xlate lookup table */
+ for (i = 0; i < num_clocks; i++)
+ max_id = max(max_id, max(data[i].master_id, data[i].slave_id));
+
+ onecell = devm_kzalloc(dev, struct_size(onecell, nodes, max_id + 1), GFP_KERNEL);
if (!onecell)
return ERR_PTR(-ENOMEM);
- onecell->num_nodes = 2 * num_clocks;
+ onecell->num_nodes = max_id + 1;
qp = devm_kzalloc(dev, struct_size(qp, clocks, num_clocks), GFP_KERNEL);
if (!qp)
@@ -106,7 +128,7 @@ struct icc_provider *icc_clk_register(struct device *dev,
icc_provider_init(provider);
- for (i = 0, j = 0; i < num_clocks; i++) {
+ for (i = 0; i < num_clocks; i++) {
qp->clocks[i].clk = data[i].clk;
node = icc_node_create(first_id + data[i].master_id);
@@ -126,7 +148,16 @@ struct icc_provider *icc_clk_register(struct device *dev,
icc_node_add(node, provider);
/* link to the next node, slave */
icc_link_create(node, first_id + data[i].slave_id);
- onecell->nodes[j++] = node;
+ onecell->nodes[data[i].master_id] = node;
+
+ /*
+ * Slave node may already be registered by an earlier
+ * master in an N:1 topology (multiple masters sharing
+ * the same slave, e.g. several CPU clusters voting on
+ * one L3 clock).
+ */
+ if (onecell->nodes[data[i].slave_id])
+ continue;
node = icc_node_create(first_id + data[i].slave_id);
if (IS_ERR(node)) {
@@ -143,7 +174,7 @@ struct icc_provider *icc_clk_register(struct device *dev,
/* no data for slave node */
icc_node_add(node, provider);
- onecell->nodes[j++] = node;
+ onecell->nodes[data[i].slave_id] = node;
}
ret = icc_provider_register(provider);
--
2.34.1
next prev parent reply other threads:[~2026-10-07 6:51 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 6:50 [PATCH 0/4] Add Qualcomm's IPQ9650 APSS Clock Driver Support Kathiravan Thirumoorthy
2026-10-07 6:50 ` Kathiravan Thirumoorthy [this message]
2026-10-16 14:12 ` [PATCH 1/4] interconnect: icc-clk: support N:1 master-to-slave topology Konrad Dybcio
2026-10-21 16:13 ` Kathiravan Thirumoorthy
2026-10-21 16:54 ` Dmitry Baryshkov
2026-10-07 6:50 ` [PATCH 2/4] clk: qcom: clk-alpha-pll: Skip Zonda PLL configuration if already enabled Kathiravan Thirumoorthy
2026-10-09 18:23 ` Abel Vesa
2026-10-16 13:50 ` Konrad Dybcio
2026-10-21 15:53 ` Kathiravan Thirumoorthy
2026-10-21 17:43 ` Dmitry Baryshkov
2026-10-07 6:50 ` [PATCH 3/4] dt-bindings: clock: ipq9650-apss-clk: Add IPQ9650 apss clock controller Kathiravan Thirumoorthy
2026-10-13 6:47 ` Krzysztof Kozlowski
2026-10-21 15:52 ` Kathiravan Thirumoorthy
2026-10-07 6:50 ` [PATCH 4/4] clk: qcom: apss-ipq9650: Add IPQ9650 APSS clock controller driver Kathiravan Thirumoorthy
2026-10-16 13:52 ` Konrad Dybcio
2026-10-21 16:11 ` Kathiravan Thirumoorthy
2026-10-21 16:56 ` [PATCH 0/4] Add Qualcomm's IPQ9650 APSS Clock Driver Support Dmitry Baryshkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261007-ipq9650_apss_clk-v1-1-fd4c2b3cbdea@oss.qualcomm.com \
--to=kathiravan.thirumoorthy@oss.qualcomm.com \
--cc=abelvesa@kernel.org \
--cc=andersson@kernel.org \
--cc=bmasney+clk@redhat.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=djakov@kernel.org \
--cc=jbrunet+clk@baylibre.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®