From: Gaowei Pu <pugaowei@oppo.com>
To: rafael@kernel.org, viresh.kumar@linaro.org,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Gaowei Pu <pugaowei@oppo.com>
Subject: [PATCH v2] cpufreq: queue policy->update work to a dedicated thread
Date: Thu, 17 Jul 2025 16:51:10 +0800 [thread overview]
Message-ID: <20250717085110.1468-1-pugaowei@oppo.com> (raw)
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@oppo.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
next reply other threads:[~2025-07-17 8:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-17 8:51 Gaowei Pu [this message]
2025-07-17 16:25 ` [PATCH v2] cpufreq: queue policy->update work to a dedicated thread Markus Elfring
2025-07-17 18:13 ` Rafael J. Wysocki
2025-07-18 7:32 ` Gaowei Pu
2025-07-18 1:57 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250717085110.1468-1-pugaowei@oppo.com \
--to=pugaowei@oppo.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=viresh.kumar@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox