[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250717085110.1468-1-pugaowei@oppo.com>
Date: Thu, 17 Jul 2025 16:51:10 +0800
From: Gaowei Pu <pugaowei@...o.com>
To: rafael@...nel.org,
viresh.kumar@...aro.org,
linux-pm@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: Gaowei Pu <pugaowei@...o.com>
Subject: [PATCH v2] cpufreq: queue policy->update work to a dedicated thread
We should ensure the low schedule latency of cpu frequency limits work
to meet performance and power demands. so queue the policy->update work
to a dedicated thread.
Remove the rt setting of the thread in patch v1 at Tim and
Rafael J's request. However, it's will not meet everyone's request
when we add a dedicated highpri workqueue to do the policy update work.
Therefore, we keep the thread and will add a vendor hook in andorid aosp
branch lately so we can customize the thread conveniently.
Changes in v2:
- Remove the rt setting of the thread and rephrase commit msg.
- Link to v1: https://lore.kernel.org/lkml/20240717063321.629-1-pugaowei@oppo.com/
Signed-off-by: Gaowei Pu <pugaowei@...o.com>
---
drivers/cpufreq/cpufreq.c | 23 +++++++++++++++++------
include/linux/cpufreq.h | 4 +++-
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d7426e1d8bdd..3980f6789a17 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1196,7 +1196,7 @@ void refresh_frequency_limits(struct cpufreq_policy *policy)
}
EXPORT_SYMBOL(refresh_frequency_limits);
-static void handle_update(struct work_struct *work)
+static void handle_update(struct kthread_work *work)
{
struct cpufreq_policy *policy =
container_of(work, struct cpufreq_policy, update);
@@ -1213,7 +1213,7 @@ static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,
{
struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_min);
- schedule_work(&policy->update);
+ kthread_queue_work(policy->worker, &policy->update);
return 0;
}
@@ -1222,7 +1222,7 @@ static int cpufreq_notifier_max(struct notifier_block *nb, unsigned long freq,
{
struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_max);
- schedule_work(&policy->update);
+ kthread_queue_work(policy->worker, &policy->update);
return 0;
}
@@ -1305,14 +1305,23 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
goto err_min_qos_notifier;
}
+ policy->worker = kthread_create_worker_on_cpu(cpu, 0, "policy_worker%d", cpu);
+ if (IS_ERR(policy->worker)) {
+ dev_err(dev, "Failed to create policy_worker%d\n", cpu);
+ goto err_max_qos_notifier;
+ }
+
INIT_LIST_HEAD(&policy->policy_list);
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
init_waitqueue_head(&policy->transition_wait);
- INIT_WORK(&policy->update, handle_update);
+ kthread_init_work(&policy->update, handle_update);
return policy;
+err_max_qos_notifier:
+ freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MAX,
+ &policy->nb_max);
err_min_qos_notifier:
freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN,
&policy->nb_min);
@@ -1356,7 +1365,9 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
&policy->nb_min);
/* Cancel any pending policy->update work before freeing the policy. */
- cancel_work_sync(&policy->update);
+ kthread_cancel_work_sync(&policy->update);
+ if (policy->worker)
+ kthread_destroy_worker(policy->worker);
if (policy->max_freq_req) {
/*
@@ -1827,7 +1838,7 @@ static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, b
cpufreq_out_of_sync(policy, new_freq);
if (update)
- schedule_work(&policy->update);
+ kthread_queue_work(policy->worker, &policy->update);
}
return new_freq;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 95f3807c8c55..728fa00a9647 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/minmax.h>
+#include <linux/kthread.h>
/*********************************************************************
* CPUFREQ INTERFACE *
@@ -77,8 +78,9 @@ struct cpufreq_policy {
void *governor_data;
char last_governor[CPUFREQ_NAME_LEN]; /* last governor used */
- struct work_struct update; /* if update_policy() needs to be
+ struct kthread_work update; /* if update_policy() needs to be
* called, but you're in IRQ context */
+ struct kthread_worker *worker;
struct freq_constraints constraints;
struct freq_qos_request *min_freq_req;
--
2.17.1
Powered by blists - more mailing lists