aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch')
-rw-r--r--target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch b/target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch
new file mode 100644
index 0000000000..12de8af22e
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/111-v5.19-04-PM-devfreq-passive-Keep-cpufreq_policy-for-possible-.patch
@@ -0,0 +1,232 @@
+From 26984d9d581e5049bd75091d2e789b9cc3ea12e0 Mon Sep 17 00:00:00 2001
+From: Chanwoo Choi <cw00.choi@samsung.com>
+Date: Wed, 27 Apr 2022 03:49:19 +0900
+Subject: [PATCH 4/5] PM / devfreq: passive: Keep cpufreq_policy for possible
+ cpus
+
+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.
+
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Johnson Wang <johnson.wang@mediatek.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+---
+ drivers/devfreq/governor.h | 3 ++
+ drivers/devfreq/governor_passive.c | 75 +++++++++++++++++++++++-------
+ include/linux/devfreq.h | 4 +-
+ 3 files changed, 64 insertions(+), 18 deletions(-)
+
+--- 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;
+
+--- a/drivers/devfreq/governor_passive.c
++++ b/drivers/devfreq/governor_passive.c
+@@ -1,4 +1,4 @@
+-// SPDX-License-Identifier: GPL-2.0-only
++ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+ * linux/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,
+@@ -51,14 +67,24 @@ static int get_target_freq_with_cpufreq(
+ 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;
+@@ -67,6 +93,7 @@ static int get_target_freq_with_cpufreq(
+ devfreq->opp_table, &cpu_cur);
+ if (freq) {
+ *target_freq = max(freq, *target_freq);
++ cpufreq_cpu_put(policy);
+ continue;
+ }
+
+@@ -81,9 +108,10 @@ static int get_target_freq_with_cpufreq(
+ 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,
+@@ -168,12 +196,11 @@ static int cpufreq_passive_notifier_call
+ 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;
+@@ -196,7 +223,7 @@ static int cpufreq_passive_unregister_no
+ 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,
+@@ -206,16 +233,26 @@ static int cpufreq_passive_unregister_no
+ }
+
+ 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)
+@@ -230,6 +267,9 @@ static int cpufreq_passive_register_noti
+ unsigned int cpu;
+ int ret;
+
++ 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) {
+@@ -239,15 +279,18 @@ static int cpufreq_passive_register_noti
+ }
+
+ 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) {
+@@ -276,7 +319,7 @@ static int cpufreq_passive_register_noti
+ 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);
+ }
+
+--- 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.
+- * @parent_cpu_data: the state min/max/current frequency of all online cpu's.
++ * @cpu_data_list: the list of cpu frequency data for all cpufreq_policy.
+ *
+ * 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
+