Skip to content

Commit 77f5032

Browse files
committed
firmware: arm_scmi: Fix possible frequency truncation when using level indexing mode
The multiplier is already promoted to unsigned long, however the frequency calculations done when using level indexing mode doesn't use the multiplier computed. It instead hardcodes the multiplier value of 1000 at all the usage sites. Clean that up by assigning the multiplier value of 1000 when using the perf level indexing mode and update the frequency calculations to use the multiplier instead. It should fix the possible frequency truncation for all the values greater than or equal to 4GHz on 64-bit machines. Fixes: 31c7c13 ("firmware: arm_scmi: Add v3.2 perf level indexing mode support") Reported-by: Sibi Sankar <quic_sibis@quicinc.com> Closes: https://lore.kernel.org/all/20231129065748.19871-3-quic_sibis@quicinc.com/ Cc: Cristian Marussi <cristian.marussi@arm.com> Link: https://lore.kernel.org/r/20231130204343.503076-2-sudeep.holla@arm.com Reviewed-by: Cristian Marussi <cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
1 parent 8e3c98d commit 77f5032

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

  • drivers/firmware/arm_scmi

drivers/firmware/arm_scmi/perf.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
268268
dom_info->sustained_perf_level =
269269
le32_to_cpu(attr->sustained_perf_level);
270270
if (!dom_info->sustained_freq_khz ||
271-
!dom_info->sustained_perf_level)
271+
!dom_info->sustained_perf_level ||
272+
dom_info->level_indexing_mode)
272273
/* CPUFreq converts to kHz, hence default 1000 */
273274
dom_info->mult_factor = 1000;
274275
else
@@ -798,7 +799,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
798799
if (!dom->level_indexing_mode)
799800
freq = dom->opp[idx].perf * dom->mult_factor;
800801
else
801-
freq = dom->opp[idx].indicative_freq * 1000;
802+
freq = dom->opp[idx].indicative_freq * dom->mult_factor;
802803

803804
data.level = dom->opp[idx].perf;
804805
data.freq = freq;
@@ -845,7 +846,8 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
845846
} else {
846847
struct scmi_opp *opp;
847848

848-
opp = LOOKUP_BY_FREQ(dom->opps_by_freq, freq / 1000);
849+
opp = LOOKUP_BY_FREQ(dom->opps_by_freq,
850+
freq / dom->mult_factor);
849851
if (!opp)
850852
return -EIO;
851853

@@ -879,7 +881,7 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
879881
if (!opp)
880882
return -EIO;
881883

882-
*freq = opp->indicative_freq * 1000;
884+
*freq = opp->indicative_freq * dom->mult_factor;
883885
}
884886

885887
return ret;
@@ -902,7 +904,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
902904
if (!dom->level_indexing_mode)
903905
opp_freq = opp->perf * dom->mult_factor;
904906
else
905-
opp_freq = opp->indicative_freq * 1000;
907+
opp_freq = opp->indicative_freq * dom->mult_factor;
906908

907909
if (opp_freq < *freq)
908910
continue;

0 commit comments

Comments
 (0)