diff options
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.patch | 85 |
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) |