Skip to content

Commit 34059ed

Browse files
Sibi Sankarvireshk
authored andcommitted
cpufreq: scmi: Register for limit change notifications
Register for limit change notifications if supported and use the throttled frequency from the notification to apply HW pressure. Signed-off-by: Sibi Sankar <[email protected]> Tested-by: Mike Tipton <[email protected]> Reviewed-by: Cristian Marussi <[email protected]> Reviewed-by: Lukasz Luba <[email protected]> Signed-off-by: Viresh Kumar <[email protected]>
1 parent 40384c8 commit 34059ed

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

drivers/cpufreq/scmi-cpufreq.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/export.h>
1717
#include <linux/module.h>
1818
#include <linux/pm_opp.h>
19+
#include <linux/pm_qos.h>
1920
#include <linux/slab.h>
2021
#include <linux/scmi_protocol.h>
2122
#include <linux/types.h>
@@ -26,6 +27,8 @@ struct scmi_data {
2627
int nr_opp;
2728
struct device *cpu_dev;
2829
cpumask_var_t opp_shared_cpus;
30+
struct notifier_block limit_notify_nb;
31+
struct freq_qos_request limits_freq_req;
2932
};
3033

3134
static struct scmi_protocol_handle *ph;
@@ -174,13 +177,30 @@ static struct freq_attr *scmi_cpufreq_hw_attr[] = {
174177
NULL,
175178
};
176179

180+
static int scmi_limit_notify_cb(struct notifier_block *nb, unsigned long event, void *data)
181+
{
182+
struct scmi_data *priv = container_of(nb, struct scmi_data, limit_notify_nb);
183+
struct scmi_perf_limits_report *limit_notify = data;
184+
unsigned int limit_freq_khz;
185+
int ret;
186+
187+
limit_freq_khz = limit_notify->range_max_freq / HZ_PER_KHZ;
188+
189+
ret = freq_qos_update_request(&priv->limits_freq_req, limit_freq_khz);
190+
if (ret < 0)
191+
pr_warn("failed to update freq constraint: %d\n", ret);
192+
193+
return NOTIFY_OK;
194+
}
195+
177196
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
178197
{
179198
int ret, nr_opp, domain;
180199
unsigned int latency;
181200
struct device *cpu_dev;
182201
struct scmi_data *priv;
183202
struct cpufreq_frequency_table *freq_table;
203+
struct scmi_device *sdev = cpufreq_get_driver_data();
184204

185205
cpu_dev = get_cpu_device(policy->cpu);
186206
if (!cpu_dev) {
@@ -294,6 +314,23 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
294314
}
295315
}
296316

317+
ret = freq_qos_add_request(&policy->constraints, &priv->limits_freq_req, FREQ_QOS_MAX,
318+
FREQ_QOS_MAX_DEFAULT_VALUE);
319+
if (ret < 0) {
320+
dev_err(cpu_dev, "failed to add qos limits request: %d\n", ret);
321+
goto out_free_table;
322+
}
323+
324+
priv->limit_notify_nb.notifier_call = scmi_limit_notify_cb;
325+
ret = sdev->handle->notify_ops->event_notifier_register(sdev->handle, SCMI_PROTOCOL_PERF,
326+
SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED,
327+
&priv->domain_id,
328+
&priv->limit_notify_nb);
329+
if (ret)
330+
dev_warn(&sdev->dev,
331+
"failed to register for limits change notifier for domain %d\n",
332+
priv->domain_id);
333+
297334
return 0;
298335

299336
out_free_table:
@@ -313,7 +350,13 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
313350
static void scmi_cpufreq_exit(struct cpufreq_policy *policy)
314351
{
315352
struct scmi_data *priv = policy->driver_data;
353+
struct scmi_device *sdev = cpufreq_get_driver_data();
316354

355+
sdev->handle->notify_ops->event_notifier_unregister(sdev->handle, SCMI_PROTOCOL_PERF,
356+
SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED,
357+
&priv->domain_id,
358+
&priv->limit_notify_nb);
359+
freq_qos_remove_request(&priv->limits_freq_req);
317360
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
318361
dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
319362
free_cpumask_var(priv->opp_shared_cpus);
@@ -372,6 +415,8 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev)
372415
if (!handle)
373416
return -ENODEV;
374417

418+
scmi_cpufreq_driver.driver_data = sdev;
419+
375420
perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph);
376421
if (IS_ERR(perf_ops))
377422
return PTR_ERR(perf_ops);

0 commit comments

Comments
 (0)