Commit 22ffc748 authored by Cristian Marussi's avatar Cristian Marussi Committed by Sudeep Holla

firmware: arm_scmi: Report frequencies in the perf notifications

Extend the perf notification report to include pre-calculated frequencies
corresponding to the reported limits/levels event; such frequencies are
properly computed based on the stored known OPPs information taking into
consideration if the current operating mode is level indexed or not.
Signed-off-by: default avatarCristian Marussi <cristian.marussi@arm.com>
Link: https://lore.kernel.org/r/20240212123233.1230090-12-cristian.marussi@arm.comSigned-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 23443a3c
...@@ -1055,18 +1055,47 @@ static int scmi_perf_set_notify_enabled(const struct scmi_protocol_handle *ph, ...@@ -1055,18 +1055,47 @@ static int scmi_perf_set_notify_enabled(const struct scmi_protocol_handle *ph,
return ret; return ret;
} }
static int
scmi_perf_xlate_opp_to_freq(struct perf_dom_info *dom,
unsigned int index, unsigned long *freq)
{
struct scmi_opp *opp;
if (!dom || !freq)
return -EINVAL;
if (!dom->level_indexing_mode) {
opp = xa_load(&dom->opps_by_lvl, index);
if (!opp)
return -ENODEV;
*freq = opp->perf * dom->mult_factor;
} else {
opp = xa_load(&dom->opps_by_idx, index);
if (!opp)
return -ENODEV;
*freq = opp->indicative_freq * dom->mult_factor;
}
return 0;
}
static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph, static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph,
u8 evt_id, ktime_t timestamp, u8 evt_id, ktime_t timestamp,
const void *payld, size_t payld_sz, const void *payld, size_t payld_sz,
void *report, u32 *src_id) void *report, u32 *src_id)
{ {
int ret;
void *rep = NULL; void *rep = NULL;
struct perf_dom_info *dom;
switch (evt_id) { switch (evt_id) {
case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED: case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED:
{ {
const struct scmi_perf_limits_notify_payld *p = payld; const struct scmi_perf_limits_notify_payld *p = payld;
struct scmi_perf_limits_report *r = report; struct scmi_perf_limits_report *r = report;
unsigned long freq_min, freq_max;
if (sizeof(*p) != payld_sz) if (sizeof(*p) != payld_sz)
break; break;
...@@ -1076,14 +1105,36 @@ static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph, ...@@ -1076,14 +1105,36 @@ static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph,
r->domain_id = le32_to_cpu(p->domain_id); r->domain_id = le32_to_cpu(p->domain_id);
r->range_max = le32_to_cpu(p->range_max); r->range_max = le32_to_cpu(p->range_max);
r->range_min = le32_to_cpu(p->range_min); r->range_min = le32_to_cpu(p->range_min);
/* Check if the reported domain exist at all */
dom = scmi_perf_domain_lookup(ph, r->domain_id);
if (IS_ERR(dom))
break;
/*
* Event will be reported from this point on...
* ...even if, later, xlated frequencies were not retrieved.
*/
*src_id = r->domain_id; *src_id = r->domain_id;
rep = r; rep = r;
ret = scmi_perf_xlate_opp_to_freq(dom, r->range_max, &freq_max);
if (ret)
break;
ret = scmi_perf_xlate_opp_to_freq(dom, r->range_min, &freq_min);
if (ret)
break;
/* Report translated freqs ONLY if both available */
r->range_max_freq = freq_max;
r->range_min_freq = freq_min;
break; break;
} }
case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED: case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED:
{ {
const struct scmi_perf_level_notify_payld *p = payld; const struct scmi_perf_level_notify_payld *p = payld;
struct scmi_perf_level_report *r = report; struct scmi_perf_level_report *r = report;
unsigned long freq;
if (sizeof(*p) != payld_sz) if (sizeof(*p) != payld_sz)
break; break;
...@@ -1091,9 +1142,27 @@ static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph, ...@@ -1091,9 +1142,27 @@ static void *scmi_perf_fill_custom_report(const struct scmi_protocol_handle *ph,
r->timestamp = timestamp; r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id); r->agent_id = le32_to_cpu(p->agent_id);
r->domain_id = le32_to_cpu(p->domain_id); r->domain_id = le32_to_cpu(p->domain_id);
/* Report translated freqs ONLY if available */
r->performance_level = le32_to_cpu(p->performance_level); r->performance_level = le32_to_cpu(p->performance_level);
/* Check if the reported domain exist at all */
dom = scmi_perf_domain_lookup(ph, r->domain_id);
if (IS_ERR(dom))
break;
/*
* Event will be reported from this point on...
* ...even if, later, xlated frequencies were not retrieved.
*/
*src_id = r->domain_id; *src_id = r->domain_id;
rep = r; rep = r;
/* Report translated freqs ONLY if available */
ret = scmi_perf_xlate_opp_to_freq(dom, r->performance_level,
&freq);
if (ret)
break;
r->performance_level_freq = freq;
break; break;
} }
default: default:
......
...@@ -956,6 +956,8 @@ struct scmi_perf_limits_report { ...@@ -956,6 +956,8 @@ struct scmi_perf_limits_report {
unsigned int domain_id; unsigned int domain_id;
unsigned int range_max; unsigned int range_max;
unsigned int range_min; unsigned int range_min;
unsigned long range_max_freq;
unsigned long range_min_freq;
}; };
struct scmi_perf_level_report { struct scmi_perf_level_report {
...@@ -963,6 +965,7 @@ struct scmi_perf_level_report { ...@@ -963,6 +965,7 @@ struct scmi_perf_level_report {
unsigned int agent_id; unsigned int agent_id;
unsigned int domain_id; unsigned int domain_id;
unsigned int performance_level; unsigned int performance_level;
unsigned long performance_level_freq;
}; };
struct scmi_sensor_trip_point_report { struct scmi_sensor_trip_point_report {
......
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