Skip to content

Commit 2d8781b

Browse files
committed
Merge tag 'scmi-fixes-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
Arm SCMI fixes for v6.7 A fix for possible truncation/overflow in the frequency computations as both the performance value and the multiplier are 32bit values. * tag 'scmi-fixes-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Fix possible frequency truncation when using level indexing mode firmware: arm_scmi: Fix frequency truncation by promoting multiplier type Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 437c99c + 77f5032 commit 2d8781b

File tree

1 file changed

+10
-8
lines changed
  • drivers/firmware/arm_scmi

1 file changed

+10
-8
lines changed

drivers/firmware/arm_scmi/perf.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ struct perf_dom_info {
152152
u32 opp_count;
153153
u32 sustained_freq_khz;
154154
u32 sustained_perf_level;
155-
u32 mult_factor;
155+
unsigned long mult_factor;
156156
struct scmi_perf_domain_info info;
157157
struct scmi_opp opp[MAX_OPPS];
158158
struct scmi_fc_info *fc_info;
@@ -268,13 +268,14 @@ 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
275276
dom_info->mult_factor =
276-
(dom_info->sustained_freq_khz * 1000) /
277-
dom_info->sustained_perf_level;
277+
(dom_info->sustained_freq_khz * 1000UL)
278+
/ dom_info->sustained_perf_level;
278279
strscpy(dom_info->info.name, attr->name,
279280
SCMI_SHORT_NAME_MAX_SIZE);
280281
}
@@ -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)