mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 05:31:08 -04:00
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]>
This commit is contained in:
1 file changed
+10
-8
@@ -152,7 +152,7 @@ struct perf_dom_info {
|
||||
u32 opp_count;
|
||||
u32 sustained_freq_khz;
|
||||
u32 sustained_perf_level;
|
||||
u32 mult_factor;
|
||||
unsigned long mult_factor;
|
||||
struct scmi_perf_domain_info info;
|
||||
struct scmi_opp opp[MAX_OPPS];
|
||||
struct scmi_fc_info *fc_info;
|
||||
@@ -268,13 +268,14 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
|
||||
dom_info->sustained_perf_level =
|
||||
le32_to_cpu(attr->sustained_perf_level);
|
||||
if (!dom_info->sustained_freq_khz ||
|
||||
!dom_info->sustained_perf_level)
|
||||
!dom_info->sustained_perf_level ||
|
||||
dom_info->level_indexing_mode)
|
||||
/* CPUFreq converts to kHz, hence default 1000 */
|
||||
dom_info->mult_factor = 1000;
|
||||
else
|
||||
dom_info->mult_factor =
|
||||
(dom_info->sustained_freq_khz * 1000) /
|
||||
dom_info->sustained_perf_level;
|
||||
(dom_info->sustained_freq_khz * 1000UL)
|
||||
/ dom_info->sustained_perf_level;
|
||||
strscpy(dom_info->info.name, attr->name,
|
||||
SCMI_SHORT_NAME_MAX_SIZE);
|
||||
}
|
||||
@@ -798,7 +799,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
|
||||
if (!dom->level_indexing_mode)
|
||||
freq = dom->opp[idx].perf * dom->mult_factor;
|
||||
else
|
||||
freq = dom->opp[idx].indicative_freq * 1000;
|
||||
freq = dom->opp[idx].indicative_freq * dom->mult_factor;
|
||||
|
||||
data.level = dom->opp[idx].perf;
|
||||
data.freq = freq;
|
||||
@@ -845,7 +846,8 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
|
||||
} else {
|
||||
struct scmi_opp *opp;
|
||||
|
||||
opp = LOOKUP_BY_FREQ(dom->opps_by_freq, freq / 1000);
|
||||
opp = LOOKUP_BY_FREQ(dom->opps_by_freq,
|
||||
freq / dom->mult_factor);
|
||||
if (!opp)
|
||||
return -EIO;
|
||||
|
||||
@@ -879,7 +881,7 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
|
||||
if (!opp)
|
||||
return -EIO;
|
||||
|
||||
*freq = opp->indicative_freq * 1000;
|
||||
*freq = opp->indicative_freq * dom->mult_factor;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -902,7 +904,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
|
||||
if (!dom->level_indexing_mode)
|
||||
opp_freq = opp->perf * dom->mult_factor;
|
||||
else
|
||||
opp_freq = opp->indicative_freq * 1000;
|
||||
opp_freq = opp->indicative_freq * dom->mult_factor;
|
||||
|
||||
if (opp_freq < *freq)
|
||||
continue;
|
||||
|
||||
Reference in new issue
Block a user