aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch')
-rw-r--r--target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch85
1 files changed, 85 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch b/target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch
new file mode 100644
index 0000000000..0883424548
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/113-v5.19-01-PM-devfreq-Fix-cpufreq-passive-unregister-errorin.patch
@@ -0,0 +1,85 @@
+From 8953603eb5447be52f6fc3d8fcae1b3ce9899189 Mon Sep 17 00:00:00 2001
+From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
+Date: Mon, 6 Jun 2022 11:58:49 +0200
+Subject: [PATCH v4 1/4] PM / devfreq: Fix cpufreq passive unregister erroring
+ on PROBE_DEFER
+
+With the passive governor, the cpu based scaling can PROBE_DEFER due to
+the fact that CPU policy are not ready.
+The cpufreq passive unregister notifier is called both from the
+GOV_START errors and for the GOV_STOP and assume the notifier is
+successfully registred every time. With GOV_START failing it's wrong to
+loop over each possible CPU since the register path has failed for
+some CPU policy not ready. Change the logic and unregister the notifer
+based on the current allocated parent_cpu_data list to correctly handle
+errors and the governor unregister path.
+
+Fixes: a03dacb0316f ("PM / devfreq: Add cpu based scaling support to passive governor")
+Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
+---
+ drivers/devfreq/governor_passive.c | 39 +++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 22 deletions(-)
+
+--- a/drivers/devfreq/governor_passive.c
++++ b/drivers/devfreq/governor_passive.c
+@@ -34,6 +34,20 @@ get_parent_cpu_data(struct devfreq_passi
+ return NULL;
+ }
+
++static void delete_parent_cpu_data(struct devfreq_passive_data *p_data)
++{
++ struct devfreq_cpu_data *parent_cpu_data, *tmp;
++
++ list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) {
++ 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);
++ }
++}
++
+ static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
+ struct opp_table *p_opp_table,
+ struct opp_table *opp_table,
+@@ -222,8 +236,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 = 0;
++ int ret;
+
+ if (p_data->nb.notifier_call) {
+ ret = cpufreq_unregister_notifier(&p_data->nb,
+@@ -232,27 +245,9 @@ static int cpufreq_passive_unregister_no
+ return ret;
+ }
+
+- for_each_possible_cpu(cpu) {
+- 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);
+- }
++ delete_parent_cpu_data(p_data);
+
+- return ret;
++ return 0;
+ }
+
+ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)