Commit 2d8781ba authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'scmi-fixes-6.7' of...

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/20231204134724.30465-1-sudeep.holla@arm.comSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 437c99c2 77f5032e
...@@ -152,7 +152,7 @@ struct perf_dom_info { ...@@ -152,7 +152,7 @@ struct perf_dom_info {
u32 opp_count; u32 opp_count;
u32 sustained_freq_khz; u32 sustained_freq_khz;
u32 sustained_perf_level; u32 sustained_perf_level;
u32 mult_factor; unsigned long mult_factor;
struct scmi_perf_domain_info info; struct scmi_perf_domain_info info;
struct scmi_opp opp[MAX_OPPS]; struct scmi_opp opp[MAX_OPPS];
struct scmi_fc_info *fc_info; struct scmi_fc_info *fc_info;
...@@ -268,13 +268,14 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, ...@@ -268,13 +268,14 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph,
dom_info->sustained_perf_level = dom_info->sustained_perf_level =
le32_to_cpu(attr->sustained_perf_level); le32_to_cpu(attr->sustained_perf_level);
if (!dom_info->sustained_freq_khz || 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 */ /* CPUFreq converts to kHz, hence default 1000 */
dom_info->mult_factor = 1000; dom_info->mult_factor = 1000;
else else
dom_info->mult_factor = dom_info->mult_factor =
(dom_info->sustained_freq_khz * 1000) / (dom_info->sustained_freq_khz * 1000UL)
dom_info->sustained_perf_level; / dom_info->sustained_perf_level;
strscpy(dom_info->info.name, attr->name, strscpy(dom_info->info.name, attr->name,
SCMI_SHORT_NAME_MAX_SIZE); SCMI_SHORT_NAME_MAX_SIZE);
} }
...@@ -798,7 +799,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph, ...@@ -798,7 +799,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
if (!dom->level_indexing_mode) if (!dom->level_indexing_mode)
freq = dom->opp[idx].perf * dom->mult_factor; freq = dom->opp[idx].perf * dom->mult_factor;
else else
freq = dom->opp[idx].indicative_freq * 1000; freq = dom->opp[idx].indicative_freq * dom->mult_factor;
data.level = dom->opp[idx].perf; data.level = dom->opp[idx].perf;
data.freq = freq; data.freq = freq;
...@@ -845,7 +846,8 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain, ...@@ -845,7 +846,8 @@ static int scmi_dvfs_freq_set(const struct scmi_protocol_handle *ph, u32 domain,
} else { } else {
struct scmi_opp *opp; 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) if (!opp)
return -EIO; return -EIO;
...@@ -879,7 +881,7 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain, ...@@ -879,7 +881,7 @@ static int scmi_dvfs_freq_get(const struct scmi_protocol_handle *ph, u32 domain,
if (!opp) if (!opp)
return -EIO; return -EIO;
*freq = opp->indicative_freq * 1000; *freq = opp->indicative_freq * dom->mult_factor;
} }
return ret; return ret;
...@@ -902,7 +904,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph, ...@@ -902,7 +904,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_protocol_handle *ph,
if (!dom->level_indexing_mode) if (!dom->level_indexing_mode)
opp_freq = opp->perf * dom->mult_factor; opp_freq = opp->perf * dom->mult_factor;
else else
opp_freq = opp->indicative_freq * 1000; opp_freq = opp->indicative_freq * dom->mult_factor;
if (opp_freq < *freq) if (opp_freq < *freq)
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment