Skip to content

Commit 17fc623

Browse files
konradybcioandersson
authored andcommitted
interconnect: qcom: icc-rpm: Fix bandwidth calculations
Up until now, we've been aggregating the bandwidth values and only dividing them by the bus width of the source node. This was completely wrong, as different nodes on a given path may (and usually do) have varying bus widths. That in turn, resulted in the calculated clock rates being completely bogus - usually they ended up being much higher, as NoC_A<->NoC_B links are very wide. Since we're not using the aggregate bandwidth value for anything other than clock rate calculations, remodel qcom_icc_bus_aggregate() to calculate the per-context clock rate for a given provider, taking into account the bus width of every individual node. Fixes: 30c8fa3 ("interconnect: qcom: Add MSM8916 interconnect provider driver") Reported-by: Stephan Gerhold <stephan@gerhold.net> Reviewed-by: Stephan Gerhold <stephan@gerhold.net> Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> Acked-by: Georgi Djakov <djakov@kernel.org> Link: https://lore.kernel.org/r/20230526-topic-smd_icc-v7-22-09c78c175546@linaro.org Signed-off-by: Bjorn Andersson <andersson@kernel.org>
1 parent 3b74801 commit 17fc623

1 file changed

Lines changed: 19 additions & 40 deletions

File tree

drivers/interconnect/qcom/icc-rpm.c

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -292,58 +292,44 @@ static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
292292
}
293293

294294
/**
295-
* qcom_icc_bus_aggregate - aggregate bandwidth by traversing all nodes
295+
* qcom_icc_bus_aggregate - calculate bus clock rates by traversing all nodes
296296
* @provider: generic interconnect provider
297-
* @agg_avg: an array for aggregated average bandwidth of buckets
298-
* @agg_peak: an array for aggregated peak bandwidth of buckets
299-
* @max_agg_avg: pointer to max value of aggregated average bandwidth
297+
* @agg_clk_rate: array containing the aggregated clock rates in kHz
300298
*/
301-
static void qcom_icc_bus_aggregate(struct icc_provider *provider,
302-
u64 *agg_avg, u64 *agg_peak,
303-
u64 *max_agg_avg)
299+
static void qcom_icc_bus_aggregate(struct icc_provider *provider, u64 *agg_clk_rate)
304300
{
305-
struct icc_node *node;
301+
u64 agg_avg_rate, agg_rate;
306302
struct qcom_icc_node *qn;
307-
u64 sum_avg[QCOM_SMD_RPM_STATE_NUM];
303+
struct icc_node *node;
308304
int i;
309305

310-
/* Initialise aggregate values */
311-
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
312-
agg_avg[i] = 0;
313-
agg_peak[i] = 0;
314-
}
315-
316-
*max_agg_avg = 0;
317-
318306
/*
319-
* Iterate nodes on the interconnect and aggregate bandwidth
320-
* requests for every bucket.
307+
* Iterate nodes on the provider, aggregate bandwidth requests for
308+
* every bucket and convert them into bus clock rates.
321309
*/
322310
list_for_each_entry(node, &provider->nodes, node_list) {
323311
qn = node->data;
324312
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
325313
if (qn->channels)
326-
sum_avg[i] = div_u64(qn->sum_avg[i], qn->channels);
314+
agg_avg_rate = div_u64(qn->sum_avg[i], qn->channels);
327315
else
328-
sum_avg[i] = qn->sum_avg[i];
329-
agg_avg[i] += sum_avg[i];
330-
agg_peak[i] = max_t(u64, agg_peak[i], qn->max_peak[i]);
316+
agg_avg_rate = qn->sum_avg[i];
317+
318+
agg_rate = max_t(u64, agg_avg_rate, qn->max_peak[i]);
319+
do_div(agg_rate, qn->buswidth);
320+
321+
agg_clk_rate[i] = max_t(u64, agg_clk_rate[i], agg_rate);
331322
}
332323
}
333-
334-
/* Find maximum values across all buckets */
335-
for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++)
336-
*max_agg_avg = max_t(u64, *max_agg_avg, agg_avg[i]);
337324
}
338325

339326
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
340327
{
341-
struct qcom_icc_provider *qp;
342328
struct qcom_icc_node *src_qn = NULL, *dst_qn = NULL;
329+
u64 agg_clk_rate[QCOM_SMD_RPM_STATE_NUM] = { 0 };
343330
struct icc_provider *provider;
331+
struct qcom_icc_provider *qp;
344332
u64 active_rate, sleep_rate;
345-
u64 agg_avg[QCOM_SMD_RPM_STATE_NUM], agg_peak[QCOM_SMD_RPM_STATE_NUM];
346-
u64 max_agg_avg;
347333
int ret;
348334

349335
src_qn = src->data;
@@ -352,7 +338,9 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
352338
provider = src->provider;
353339
qp = to_qcom_provider(provider);
354340

355-
qcom_icc_bus_aggregate(provider, agg_avg, agg_peak, &max_agg_avg);
341+
qcom_icc_bus_aggregate(provider, agg_clk_rate);
342+
active_rate = agg_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE];
343+
sleep_rate = agg_clk_rate[QCOM_SMD_RPM_SLEEP_STATE];
356344

357345
ret = qcom_icc_rpm_set(src_qn, src_qn->sum_avg);
358346
if (ret)
@@ -368,15 +356,6 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
368356
if (!qp->bus_clk_desc && !qp->bus_clk)
369357
return 0;
370358

371-
/* Intentionally keep the rates in kHz as that's what RPM accepts */
372-
active_rate = max(agg_avg[QCOM_SMD_RPM_ACTIVE_STATE],
373-
agg_peak[QCOM_SMD_RPM_ACTIVE_STATE]);
374-
do_div(active_rate, src_qn->buswidth);
375-
376-
sleep_rate = max(agg_avg[QCOM_SMD_RPM_SLEEP_STATE],
377-
agg_peak[QCOM_SMD_RPM_SLEEP_STATE]);
378-
do_div(sleep_rate, src_qn->buswidth);
379-
380359
/*
381360
* Downstream checks whether the requested rate is zero, but it makes little sense
382361
* to vote for a value that's below the lower threshold, so let's not do so.

0 commit comments

Comments
 (0)