* [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read
@ 2026-09-08 8:09 Neil Armstrong
2026-09-08 14:39 ` Maulik Shah
2026-09-09 7:48 ` kernel test robot
0 siblings, 2 replies; 4+ messages in thread
From: Neil Armstrong @ 2026-09-08 8:09 UTC (permalink / raw)
To: Georgi Djakov; +Cc: linux-arm-msm, linux-pm, linux-kernel, Neil Armstrong
Since we can actually read back the APPS rpmh interconnect
BCM votes we can actually implement the get_bw() callback
and provide a coherent average and peak bandwidth at probe time.
The benefits of that are:
- keep disabled BCMs disabled
- avoid voting unused BCMs to INT_MAX
If the interconnects are correctly described for a platform,
all the required BCMs would be voted to the maximum bandwidth
until sync_state is reached.
Since we only get the BCM vote, we need to redistribute
the vote values to the associated nodes. The initial BCM
votes are read back at probe time in order to be ready when
the get_bw() is called when a node is added.
Tested-by: Georgi Djakov <djakov@kernel.org> #db845c
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Changes in v2:
- Added tested-by
- Rebased on v7.3-rc1 now the rpmh_read() is merged
- Link to v1: https://patch.msgid.link/20251106-topic-sm8x50-icc-read-rpmh-v1-1-d03a2e5ca5f7@linaro.org
---
drivers/interconnect/qcom/bcm-voter.c | 36 +++++++++++++++++++++
drivers/interconnect/qcom/bcm-voter.h | 1 +
drivers/interconnect/qcom/icc-rpmh.c | 60 ++++++++++++++++++++++++++++++++++-
3 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
index a2d437a05a11..9014bf20adad 100644
--- a/drivers/interconnect/qcom/bcm-voter.c
+++ b/drivers/interconnect/qcom/bcm-voter.c
@@ -261,6 +261,42 @@ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
}
EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_add);
+/**
+ * qcom_icc_bcm_get_bw - get current bcm vote
+ * @voter: voter used to query bcm
+ * @bcm: bcm to get current vote from
+ */
+void qcom_icc_bcm_get_bw(struct bcm_voter *voter,
+ struct qcom_icc_bcm *bcm)
+{
+ struct tcs_cmd cmd = { .addr = bcm->addr };
+ int ret, i;
+ u64 x, y;
+
+ mutex_lock(&voter->lock);
+
+ rpmh_invalidate(voter->dev);
+
+ ret = rpmh_read(voter->dev, &cmd);
+ if (ret) {
+ pr_err("Error sending AMC RPMH requests (%d)\n", ret);
+ goto out;
+ }
+
+ x = FIELD_GET(BCM_TCS_CMD_VOTE_X_MASK, cmd.data);
+ y = FIELD_GET(BCM_TCS_CMD_VOTE_Y_MASK, cmd.data);
+
+ /* For boot-up, fill the AMC vote in all buckets */
+ for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
+ bcm->vote_x[i] = x;
+ bcm->vote_y[i] = y;
+ }
+
+out:
+ mutex_unlock(&voter->lock);
+}
+EXPORT_SYMBOL_GPL(qcom_icc_bcm_get_bw);
+
/**
* qcom_icc_bcm_voter_commit - generates and commits tcs cmds based on bcms
* @voter: voter that needs flushing
diff --git a/drivers/interconnect/qcom/bcm-voter.h b/drivers/interconnect/qcom/bcm-voter.h
index b4d36e349f3c..fc75d457dcc7 100644
--- a/drivers/interconnect/qcom/bcm-voter.h
+++ b/drivers/interconnect/qcom/bcm-voter.h
@@ -13,6 +13,7 @@
#include "icc-rpmh.h"
struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name);
+void qcom_icc_bcm_get_bw(struct bcm_voter *voter, struct qcom_icc_bcm *bcm);
void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm);
int qcom_icc_bcm_voter_commit(struct bcm_voter *voter);
diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c
index 3b445acefece..7f2b5673629b 100644
--- a/drivers/interconnect/qcom/icc-rpmh.c
+++ b/drivers/interconnect/qcom/icc-rpmh.c
@@ -136,6 +136,61 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
}
EXPORT_SYMBOL_GPL(qcom_icc_set);
+static int qcom_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ struct qcom_icc_node *qn = node->data;
+ u32 avg_max = 0;
+ u32 peak_max = 0;
+ u64 x, y;
+ int i;
+
+ if (!qn->num_bcms) {
+ *avg = INT_MAX;
+ *peak = INT_MAX;
+
+ return 0;
+ }
+
+ for (i = 0; i < qn->num_bcms; ++i) {
+ struct qcom_icc_bcm *bcm = qn->bcms[i];
+
+ /* Use AMC vote for boot-up */
+ x = bcm->vote_x[QCOM_ICC_BUCKET_AMC];
+ y = bcm->vote_y[QCOM_ICC_BUCKET_AMC];
+
+ /* Consider enable mask and convert to INT_MAX */
+ if (bcm->enable_mask) {
+ if (x & bcm->enable_mask)
+ avg_max = INT_MAX;
+ if (y & bcm->enable_mask)
+ peak_max = INT_MAX;
+ } else {
+ if (x) {
+ x *= bcm->aux_data.unit;
+ do_div(x, bcm->vote_scale);
+ x *= qn->buswidth * qn->channels;
+ do_div(x, bcm->aux_data.width);
+
+ avg_max = max(avg_max, x);
+ }
+
+ if (y) {
+ y *= bcm->aux_data.unit;
+ do_div(y, bcm->vote_scale);
+ y *= qn->buswidth;
+ do_div(y, bcm->aux_data.width);
+
+ peak_max = max(peak_max, y);
+ }
+ }
+ }
+
+ *avg = avg_max;
+ *peak = peak_max;
+
+ return 0;
+}
+
/**
* qcom_icc_bcm_init - populates bcm aux data and connect qnodes
* @bcm: bcm to be initialized
@@ -255,6 +310,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
provider = &qp->provider;
provider->dev = dev;
provider->set = qcom_icc_set;
+ provider->get_bw = qcom_icc_get_bw;
provider->pre_aggregate = qcom_icc_pre_aggregate;
provider->aggregate = qcom_icc_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
@@ -272,8 +328,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
if (IS_ERR(qp->voter))
return PTR_ERR(qp->voter);
- for (i = 0; i < qp->num_bcms; i++)
+ for (i = 0; i < qp->num_bcms; i++) {
qcom_icc_bcm_init(qp->bcms[i], dev);
+ qcom_icc_bcm_get_bw(qp->voter, qp->bcms[i]);
+ }
for (i = 0; i < num_nodes; i++) {
qn = qnodes[i];
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20251106-topic-sm8x50-icc-read-rpmh-eba461a452e7
Best regards,
--
Neil Armstrong <neil.armstrong@linaro.org>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read
2026-09-08 8:09 [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read Neil Armstrong
@ 2026-09-08 14:39 ` Maulik Shah
2026-09-09 7:16 ` Neil Armstrong
2026-09-09 7:48 ` kernel test robot
1 sibling, 1 reply; 4+ messages in thread
From: Maulik Shah @ 2026-09-08 14:39 UTC (permalink / raw)
To: Neil Armstrong, Georgi Djakov; +Cc: linux-arm-msm, linux-pm, linux-kernel
On 08-09-2026 13:39, Neil Armstrong wrote:
> Since we can actually read back the APPS rpmh interconnect
> BCM votes we can actually implement the get_bw() callback
> and provide a coherent average and peak bandwidth at probe time.
>
> The benefits of that are:
> - keep disabled BCMs disabled
> - avoid voting unused BCMs to INT_MAX
>
> If the interconnects are correctly described for a platform,
> all the required BCMs would be voted to the maximum bandwidth
> until sync_state is reached.
>
> Since we only get the BCM vote, we need to redistribute
> the vote values to the associated nodes. The initial BCM
> votes are read back at probe time in order to be ready when
> the get_bw() is called when a node is added.
>
> Tested-by: Georgi Djakov <djakov@kernel.org> #db845c
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> Changes in v2:
> - Added tested-by
> - Rebased on v7.3-rc1 now the rpmh_read() is merged
> - Link to v1: https://patch.msgid.link/20251106-topic-sm8x50-icc-read-rpmh-v1-1-d03a2e5ca5f7@linaro.org
> ---
> drivers/interconnect/qcom/bcm-voter.c | 36 +++++++++++++++++++++
> drivers/interconnect/qcom/bcm-voter.h | 1 +
> drivers/interconnect/qcom/icc-rpmh.c | 60 ++++++++++++++++++++++++++++++++++-
> 3 files changed, 96 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
> index a2d437a05a11..9014bf20adad 100644
> --- a/drivers/interconnect/qcom/bcm-voter.c
> +++ b/drivers/interconnect/qcom/bcm-voter.c
> @@ -261,6 +261,42 @@ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
> }
> EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_add);
>
> +/**
> + * qcom_icc_bcm_get_bw - get current bcm vote
> + * @voter: voter used to query bcm
> + * @bcm: bcm to get current vote from
> + */
> +void qcom_icc_bcm_get_bw(struct bcm_voter *voter,
> + struct qcom_icc_bcm *bcm)
> +{
> + struct tcs_cmd cmd = { .addr = bcm->addr };
> + int ret, i;
> + u64 x, y;
> +
> + mutex_lock(&voter->lock);
> +
> + rpmh_invalidate(voter->dev);
Don't see why rpmh_invalidate() is needed before a read request.
Thanks,
Maulik
> +
> + ret = rpmh_read(voter->dev, &cmd);
> + if (ret) {
> + pr_err("Error sending AMC RPMH requests (%d)\n", ret);
> + goto out;
> + }
> +
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read
2026-09-08 14:39 ` Maulik Shah
@ 2026-09-09 7:16 ` Neil Armstrong
0 siblings, 0 replies; 4+ messages in thread
From: Neil Armstrong @ 2026-09-09 7:16 UTC (permalink / raw)
To: Maulik Shah, Georgi Djakov; +Cc: linux-arm-msm, linux-pm, linux-kernel
On 9/8/26 16:39, Maulik Shah wrote:
>
> On 08-09-2026 13:39, Neil Armstrong wrote:
>> Since we can actually read back the APPS rpmh interconnect
>> BCM votes we can actually implement the get_bw() callback
>> and provide a coherent average and peak bandwidth at probe time.
>>
>> The benefits of that are:
>> - keep disabled BCMs disabled
>> - avoid voting unused BCMs to INT_MAX
>>
>> If the interconnects are correctly described for a platform,
>> all the required BCMs would be voted to the maximum bandwidth
>> until sync_state is reached.
>>
>> Since we only get the BCM vote, we need to redistribute
>> the vote values to the associated nodes. The initial BCM
>> votes are read back at probe time in order to be ready when
>> the get_bw() is called when a node is added.
>>
>> Tested-by: Georgi Djakov <djakov@kernel.org> #db845c
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>> Changes in v2:
>> - Added tested-by
>> - Rebased on v7.3-rc1 now the rpmh_read() is merged
>> - Link to v1: https://patch.msgid.link/20251106-topic-sm8x50-icc-read-rpmh-v1-1-d03a2e5ca5f7@linaro.org
>> ---
>> drivers/interconnect/qcom/bcm-voter.c | 36 +++++++++++++++++++++
>> drivers/interconnect/qcom/bcm-voter.h | 1 +
>> drivers/interconnect/qcom/icc-rpmh.c | 60 ++++++++++++++++++++++++++++++++++-
>> 3 files changed, 96 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
>> index a2d437a05a11..9014bf20adad 100644
>> --- a/drivers/interconnect/qcom/bcm-voter.c
>> +++ b/drivers/interconnect/qcom/bcm-voter.c
>> @@ -261,6 +261,42 @@ void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm)
>> }
>> EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_add);
>>
>> +/**
>> + * qcom_icc_bcm_get_bw - get current bcm vote
>> + * @voter: voter used to query bcm
>> + * @bcm: bcm to get current vote from
>> + */
>> +void qcom_icc_bcm_get_bw(struct bcm_voter *voter,
>> + struct qcom_icc_bcm *bcm)
>> +{
>> + struct tcs_cmd cmd = { .addr = bcm->addr };
>> + int ret, i;
>> + u64 x, y;
>> +
>> + mutex_lock(&voter->lock);
>> +
>> + rpmh_invalidate(voter->dev);
>
> Don't see why rpmh_invalidate() is needed before a read request.
You're right, will drop.
Thanks,
Neil
>
> Thanks,
> Maulik
>
>> +
>> + ret = rpmh_read(voter->dev, &cmd);
>> + if (ret) {
>> + pr_err("Error sending AMC RPMH requests (%d)\n", ret);
>> + goto out;
>> + }
>> +
>>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read
2026-09-08 8:09 [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read Neil Armstrong
2026-09-08 14:39 ` Maulik Shah
@ 2026-09-09 7:48 ` kernel test robot
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2026-09-09 7:48 UTC (permalink / raw)
To: Neil Armstrong, Georgi Djakov
Cc: oe-kbuild-all, linux-arm-msm, linux-pm, linux-kernel, Neil Armstrong
Hi Neil,
kernel test robot noticed the following build warnings:
[auto build test WARNING on cee9395acd8043be0644b25c34bfa86623f2b935]
url: https://github.com/intel-lab-lkp/linux/commits/Neil-Armstrong/interconnect-qcom-implement-get_bw-with-rpmh_read/20260908-100915
base: cee9395acd8043be0644b25c34bfa86623f2b935
patch link: https://lore.kernel.org/r/20260908-topic-sm8x50-icc-read-rpmh-v2-1-b6f1c4205450%40linaro.org
patch subject: [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read
config: arc-randconfig-r112-20260909 (https://download.01.org/0day-ci/archive/20260909/202609091547.IZVghFTg-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 10.5.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260909/202609091547.IZVghFTg-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609091547.IZVghFTg-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> drivers/interconnect/qcom/icc-rpmh.c:169:35: sparse: sparse: invalid assignment: *=
drivers/interconnect/qcom/icc-rpmh.c:169:35: sparse: left side has type unsigned long long
drivers/interconnect/qcom/icc-rpmh.c:169:35: sparse: right side has type restricted __le32
>> drivers/interconnect/qcom/icc-rpmh.c:172:33: sparse: sparse: incorrect type in initializer (different base types) @@ expected unsigned int [usertype] __base @@ got restricted __le16 [usertype] width @@
drivers/interconnect/qcom/icc-rpmh.c:172:33: sparse: expected unsigned int [usertype] __base
drivers/interconnect/qcom/icc-rpmh.c:172:33: sparse: got restricted __le16 [usertype] width
drivers/interconnect/qcom/icc-rpmh.c:178:35: sparse: sparse: invalid assignment: *=
drivers/interconnect/qcom/icc-rpmh.c:178:35: sparse: left side has type unsigned long long
drivers/interconnect/qcom/icc-rpmh.c:178:35: sparse: right side has type restricted __le32
drivers/interconnect/qcom/icc-rpmh.c:181:33: sparse: sparse: incorrect type in initializer (different base types) @@ expected unsigned int [usertype] __base @@ got restricted __le16 [usertype] width @@
drivers/interconnect/qcom/icc-rpmh.c:181:33: sparse: expected unsigned int [usertype] __base
drivers/interconnect/qcom/icc-rpmh.c:181:33: sparse: got restricted __le16 [usertype] width
drivers/interconnect/qcom/icc-rpmh.c:231:28: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __le32 [usertype] unit @@ got unsigned int [usertype] @@
drivers/interconnect/qcom/icc-rpmh.c:231:28: sparse: expected restricted __le32 [usertype] unit
drivers/interconnect/qcom/icc-rpmh.c:231:28: sparse: got unsigned int [usertype]
drivers/interconnect/qcom/icc-rpmh.c:232:29: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted __le16 [usertype] width @@ got unsigned short [usertype] @@
drivers/interconnect/qcom/icc-rpmh.c:232:29: sparse: expected restricted __le16 [usertype] width
drivers/interconnect/qcom/icc-rpmh.c:232:29: sparse: got unsigned short [usertype]
vim +169 drivers/interconnect/qcom/icc-rpmh.c
138
139 static int qcom_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
140 {
141 struct qcom_icc_node *qn = node->data;
142 u32 avg_max = 0;
143 u32 peak_max = 0;
144 u64 x, y;
145 int i;
146
147 if (!qn->num_bcms) {
148 *avg = INT_MAX;
149 *peak = INT_MAX;
150
151 return 0;
152 }
153
154 for (i = 0; i < qn->num_bcms; ++i) {
155 struct qcom_icc_bcm *bcm = qn->bcms[i];
156
157 /* Use AMC vote for boot-up */
158 x = bcm->vote_x[QCOM_ICC_BUCKET_AMC];
159 y = bcm->vote_y[QCOM_ICC_BUCKET_AMC];
160
161 /* Consider enable mask and convert to INT_MAX */
162 if (bcm->enable_mask) {
163 if (x & bcm->enable_mask)
164 avg_max = INT_MAX;
165 if (y & bcm->enable_mask)
166 peak_max = INT_MAX;
167 } else {
168 if (x) {
> 169 x *= bcm->aux_data.unit;
170 do_div(x, bcm->vote_scale);
171 x *= qn->buswidth * qn->channels;
> 172 do_div(x, bcm->aux_data.width);
173
174 avg_max = max(avg_max, x);
175 }
176
177 if (y) {
178 y *= bcm->aux_data.unit;
179 do_div(y, bcm->vote_scale);
180 y *= qn->buswidth;
181 do_div(y, bcm->aux_data.width);
182
183 peak_max = max(peak_max, y);
184 }
185 }
186 }
187
188 *avg = avg_max;
189 *peak = peak_max;
190
191 return 0;
192 }
193
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-09 7:50 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08 8:09 [PATCH v2] interconnect: qcom: implement get_bw with rpmh_read Neil Armstrong
2026-09-08 14:39 ` Maulik Shah
2026-09-09 7:16 ` Neil Armstrong
2026-09-09 7:48 ` kernel test robot
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®