lkml.org 
[lkml]   [2023]   [May]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Date
Subject[PATCH 20/20] interconnect: qcom: Divide clk rate by src node bus width
Ever since the introduction of SMD RPM ICC, we've been dividing the
clock rate by the wrong bus width. This has resulted in:

- setting wrong (mostly too low) rates, affecting performance
- most often /2 or /4
- things like DDR never hit their full potential
- the rates were only correct if src bus width == dst bus width
for all src, dst pairs on a given bus

- Qualcomm using the same wrong logic in their BSP driver in msm-5.x
that ships in production devices today

- me losing my sanity trying to find this

Resolve it by using dst_qn, if it exists.

Fixes: 5e4e6c4d3ae0 ("interconnect: qcom: Add QCS404 interconnect provider driver")
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
---
drivers/interconnect/qcom/icc-rpm.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 59be704364bb..58e2a8b1b7c3 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -340,7 +340,7 @@ static void qcom_icc_bus_aggregate(struct icc_provider *provider,
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct qcom_icc_provider *qp;
- struct qcom_icc_node *src_qn = NULL, *dst_qn = NULL;
+ struct qcom_icc_node *src_qn = NULL, *dst_qn = NULL, *qn = NULL;
struct icc_provider *provider;
u64 active_rate, sleep_rate;
u64 agg_avg[QCOM_SMD_RPM_STATE_NUM], agg_peak[QCOM_SMD_RPM_STATE_NUM];
@@ -353,6 +353,8 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
provider = src->provider;
qp = to_qcom_provider(provider);

+ qn = dst_qn ? dst_qn : src_qn;
+
qcom_icc_bus_aggregate(provider, agg_avg, agg_peak, &max_agg_avg);

ret = qcom_icc_rpm_set(src_qn, agg_avg);
@@ -372,11 +374,11 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
/* Intentionally keep the rates in kHz as that's what RPM accepts */
active_rate = max(agg_avg[QCOM_SMD_RPM_ACTIVE_STATE],
agg_peak[QCOM_SMD_RPM_ACTIVE_STATE]);
- do_div(active_rate, src_qn->buswidth);
+ do_div(active_rate, qn->buswidth);

sleep_rate = max(agg_avg[QCOM_SMD_RPM_SLEEP_STATE],
agg_peak[QCOM_SMD_RPM_SLEEP_STATE]);
- do_div(sleep_rate, src_qn->buswidth);
+ do_div(sleep_rate, qn->buswidth);

/*
* Downstream checks whether the requested rate is zero, but it makes little sense
--
2.40.1

\
 
 \ /
  Last update: 2023-05-30 12:23    [W:0.487 / U:0.060 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site