From: Chanwoo Choi <cwchoi00@gmail.com>
To: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: johnson.wang@mediatek.com, mka@chromium.org, wenst@chromium.org,
jia-wei.chang@mediatek.com, andrew-sh.cheng@mediatek.com,
hsinyi@chromium.org, saravanak@google.com, cw00.choi@samsung.com,
myungjoo.ham@samsung.com, kyungmin.park@samsung.com
Subject: [PATCH v3 4/4] PM / devfreq: passive: Keep cpufreq_policy for possible cpus
Date: Mon, 9 May 2022 21:03:37 +0900 [thread overview]
Message-ID: <20220509120337.92472-5-cw00.choi@samsung.com> (raw)
In-Reply-To: <20220509120337.92472-1-cw00.choi@samsung.com>
The passive governor requires the cpu data to get the next target frequency
of devfreq device if depending on cpu. In order to reduce the unnecessary
memory data, keep cpufreq_policy data for possible cpus instead of NR_CPU.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
drivers/devfreq/governor.h | 3 ++
drivers/devfreq/governor_passive.c | 73 ++++++++++++++++++++++++------
include/linux/devfreq.h | 4 +-
3 files changed, 63 insertions(+), 17 deletions(-)
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index 335c4a491254..0adfebc0467a 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -49,6 +49,7 @@
/**
* struct devfreq_cpu_data - Hold the per-cpu data
+ * @node: list node
* @dev: reference to cpu device.
* @first_cpu: the cpumask of the first cpu of a policy.
* @opp_table: reference to cpu opp table.
@@ -60,6 +61,8 @@
* This is auto-populated by the governor.
*/
struct devfreq_cpu_data {
+ struct list_head node;
+
struct device *dev;
unsigned int first_cpu;
diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
index db02f5219684..331e93b9eb8d 100644
--- a/drivers/devfreq/governor_passive.c
+++ b/drivers/devfreq/governor_passive.c
@@ -18,6 +18,22 @@
#define HZ_PER_KHZ 1000
+static struct devfreq_cpu_data *
+get_parent_cpu_data(struct devfreq_passive_data *p_data,
+ struct cpufreq_policy *policy)
+{
+ struct devfreq_cpu_data *parent_cpu_data;
+
+ if (!p_data || !policy)
+ return NULL;
+
+ list_for_each_entry(parent_cpu_data, &p_data->cpu_data_list, node)
+ if (parent_cpu_data->first_cpu == cpumask_first(policy->related_cpus))
+ return parent_cpu_data;
+
+ return NULL;
+}
+
static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
struct opp_table *p_opp_table,
struct opp_table *opp_table,
@@ -50,14 +66,24 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
struct devfreq_passive_data *p_data =
(struct devfreq_passive_data *)devfreq->data;
struct devfreq_cpu_data *parent_cpu_data;
+ struct cpufreq_policy *policy;
unsigned long cpu, cpu_cur, cpu_min, cpu_max, cpu_percent;
unsigned long dev_min, dev_max;
unsigned long freq = 0;
+ int ret = 0;
for_each_online_cpu(cpu) {
- parent_cpu_data = p_data->parent_cpu_data[cpu];
- if (!parent_cpu_data || parent_cpu_data->first_cpu != cpu)
+ policy = cpufreq_cpu_get(cpu);
+ if (!policy) {
+ ret = -EINVAL;
+ continue;
+ }
+
+ parent_cpu_data = get_parent_cpu_data(p_data, policy);
+ if (!parent_cpu_data) {
+ cpufreq_cpu_put(policy);
continue;
+ }
/* Get target freq via required opps */
cpu_cur = parent_cpu_data->cur_freq * HZ_PER_KHZ;
@@ -66,6 +92,7 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
devfreq->opp_table, cpu_cur);
if (freq) {
*target_freq = max(freq, *target_freq);
+ cpufreq_cpu_put(policy);
continue;
}
@@ -80,9 +107,10 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
freq = dev_min + mult_frac(dev_max - dev_min, cpu_percent, 100);
*target_freq = max(freq, *target_freq);
+ cpufreq_cpu_put(policy);
}
- return 0;
+ return ret;
}
static int get_target_freq_with_devfreq(struct devfreq *devfreq,
@@ -167,12 +195,11 @@ static int cpufreq_passive_notifier_call(struct notifier_block *nb,
unsigned int cur_freq;
int ret;
- if (event != CPUFREQ_POSTCHANGE || !freqs ||
- !p_data->parent_cpu_data[freqs->policy->cpu])
+ if (event != CPUFREQ_POSTCHANGE || !freqs)
return 0;
- parent_cpu_data = p_data->parent_cpu_data[freqs->policy->cpu];
- if (parent_cpu_data->cur_freq == freqs->new)
+ parent_cpu_data = get_parent_cpu_data(p_data, freqs->policy);
+ if (!parent_cpu_data || parent_cpu_data->cur_freq == freqs->new)
return 0;
cur_freq = parent_cpu_data->cur_freq;
@@ -195,7 +222,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
struct devfreq_passive_data *p_data
= (struct devfreq_passive_data *)devfreq->data;
struct devfreq_cpu_data *parent_cpu_data;
- int cpu, ret;
+ int cpu, ret = 0;
if (p_data->nb.notifier_call) {
ret = cpufreq_unregister_notifier(&p_data->nb,
@@ -205,16 +232,26 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
}
for_each_possible_cpu(cpu) {
- parent_cpu_data = p_data->parent_cpu_data[cpu];
- if (!parent_cpu_data)
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ if (!policy) {
+ ret = -EINVAL;
continue;
+ }
+ parent_cpu_data = get_parent_cpu_data(p_data, policy);
+ if (!parent_cpu_data) {
+ cpufreq_cpu_put(policy);
+ continue;
+ }
+
+ list_del(&parent_cpu_data->node);
if (parent_cpu_data->opp_table)
dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
kfree(parent_cpu_data);
+ cpufreq_cpu_put(policy);
}
- return 0;
+ return ret;
}
static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
@@ -232,6 +269,9 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
if (!p_data->this)
p_data->this = devfreq;
+ p_data->cpu_data_list
+ = (struct list_head)LIST_HEAD_INIT(p_data->cpu_data_list);
+
p_data->nb.notifier_call = cpufreq_passive_notifier_call;
ret = cpufreq_register_notifier(&p_data->nb, CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
@@ -241,15 +281,18 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
}
for_each_possible_cpu(cpu) {
- if (p_data->parent_cpu_data[cpu])
- continue;
-
policy = cpufreq_cpu_get(cpu);
if (!policy) {
ret = -EPROBE_DEFER;
goto err;
}
+ parent_cpu_data = get_parent_cpu_data(p_data, policy);
+ if (parent_cpu_data) {
+ cpufreq_cpu_put(policy);
+ continue;
+ }
+
parent_cpu_data = kzalloc(sizeof(*parent_cpu_data),
GFP_KERNEL);
if (!parent_cpu_data) {
@@ -278,7 +321,7 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
parent_cpu_data->min_freq = policy->cpuinfo.min_freq;
parent_cpu_data->max_freq = policy->cpuinfo.max_freq;
- p_data->parent_cpu_data[cpu] = parent_cpu_data;
+ list_add_tail(&parent_cpu_data->node, &p_data->cpu_data_list);
cpufreq_cpu_put(policy);
}
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index ccebb5c84d62..2fca831db564 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -309,7 +309,7 @@ enum devfreq_parent_dev_type {
+ * @this: the devfreq instance of own device.
+ * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER or
* CPUFREQ_TRANSITION_NOTIFIER list.
- + * @cpu_data: the state min/max/current frequency of all online cpu's
+ + * @cpu_data_list: the cpufreq_policy list of all possible cpus.
*
* The devfreq_passive_data have to set the devfreq instance of parent
* device with governors except for the passive governor. But, don't need to
@@ -329,7 +329,7 @@ struct devfreq_passive_data {
/* For passive governor's internal use. Don't need to set them */
struct devfreq *this;
struct notifier_block nb;
- struct devfreq_cpu_data *parent_cpu_data[NR_CPUS];
+ struct list_head cpu_data_list;
};
#endif
--
2.25.1
next prev parent reply other threads:[~2022-05-09 12:04 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-09 12:03 [PATCH v3 0/4] PM / devfreq: Add cpu based scaling support to passive governor Chanwoo Choi
2022-05-09 12:03 ` [PATCH v3 1/4] PM / devfreq: Export devfreq_get_freq_range symbol within devfreq Chanwoo Choi
2022-05-09 12:03 ` [PATCH v3 2/4] PM / devfreq: Add cpu based scaling support to passive governor Chanwoo Choi
2022-05-09 18:01 ` Chanwoo Choi
2022-05-09 12:03 ` [PATCH v3 3/4] PM / devfreq: passive: Reduce duplicate code when passive_devfreq case Chanwoo Choi
2022-05-09 12:03 ` Chanwoo Choi [this message]
2022-05-10 9:00 ` [PATCH v3 0/4] PM / devfreq: Add cpu based scaling support to passive governor Chen-Yu Tsai
2022-05-10 9:08 ` Chanwoo Choi
2022-05-11 5:29 ` Johnson Wang
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=20220509120337.92472-5-cw00.choi@samsung.com \
--to=cwchoi00@gmail.com \
--cc=andrew-sh.cheng@mediatek.com \
--cc=cw00.choi@samsung.com \
--cc=hsinyi@chromium.org \
--cc=jia-wei.chang@mediatek.com \
--cc=johnson.wang@mediatek.com \
--cc=kyungmin.park@samsung.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mka@chromium.org \
--cc=myungjoo.ham@samsung.com \
--cc=saravanak@google.com \
--cc=wenst@chromium.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;
as well as URLs for NNTP newsgroup(s).