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 <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Cc: Cristian Marussi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 8e3c98d commit 77f5032

File tree

1 file changed

+7
-5
lines changed
  • drivers/firmware/arm_scmi

1 file changed

+7
-5
lines changed

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)