088342454869b68219dab602bba821d0c3d1c33d
[openwrt/staging/stintel.git] /
1 From 8953603eb5447be52f6fc3d8fcae1b3ce9899189 Mon Sep 17 00:00:00 2001
2 From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
3 Date: Mon, 6 Jun 2022 11:58:49 +0200
4 Subject: [PATCH v4 1/4] PM / devfreq: Fix cpufreq passive unregister erroring
5 on PROBE_DEFER
6
7 With the passive governor, the cpu based scaling can PROBE_DEFER due to
8 the fact that CPU policy are not ready.
9 The cpufreq passive unregister notifier is called both from the
10 GOV_START errors and for the GOV_STOP and assume the notifier is
11 successfully registred every time. With GOV_START failing it's wrong to
12 loop over each possible CPU since the register path has failed for
13 some CPU policy not ready. Change the logic and unregister the notifer
14 based on the current allocated parent_cpu_data list to correctly handle
15 errors and the governor unregister path.
16
17 Fixes: a03dacb0316f ("PM / devfreq: Add cpu based scaling support to passive governor")
18 Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
19 ---
20 drivers/devfreq/governor_passive.c | 39 +++++++++++++-----------------
21 1 file changed, 17 insertions(+), 22 deletions(-)
22
23 --- a/drivers/devfreq/governor_passive.c
24 +++ b/drivers/devfreq/governor_passive.c
25 @@ -34,6 +34,20 @@ get_parent_cpu_data(struct devfreq_passi
26 return NULL;
27 }
28
29 +static void delete_parent_cpu_data(struct devfreq_passive_data *p_data)
30 +{
31 + struct devfreq_cpu_data *parent_cpu_data, *tmp;
32 +
33 + list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) {
34 + list_del(&parent_cpu_data->node);
35 +
36 + if (parent_cpu_data->opp_table)
37 + dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
38 +
39 + kfree(parent_cpu_data);
40 + }
41 +}
42 +
43 static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
44 struct opp_table *p_opp_table,
45 struct opp_table *opp_table,
46 @@ -222,8 +236,7 @@ static int cpufreq_passive_unregister_no
47 {
48 struct devfreq_passive_data *p_data
49 = (struct devfreq_passive_data *)devfreq->data;
50 - struct devfreq_cpu_data *parent_cpu_data;
51 - int cpu, ret = 0;
52 + int ret;
53
54 if (p_data->nb.notifier_call) {
55 ret = cpufreq_unregister_notifier(&p_data->nb,
56 @@ -232,27 +245,9 @@ static int cpufreq_passive_unregister_no
57 return ret;
58 }
59
60 - for_each_possible_cpu(cpu) {
61 - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
62 - if (!policy) {
63 - ret = -EINVAL;
64 - continue;
65 - }
66 -
67 - parent_cpu_data = get_parent_cpu_data(p_data, policy);
68 - if (!parent_cpu_data) {
69 - cpufreq_cpu_put(policy);
70 - continue;
71 - }
72 -
73 - list_del(&parent_cpu_data->node);
74 - if (parent_cpu_data->opp_table)
75 - dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
76 - kfree(parent_cpu_data);
77 - cpufreq_cpu_put(policy);
78 - }
79 + delete_parent_cpu_data(p_data);
80
81 - return ret;
82 + return 0;
83 }
84
85 static int cpufreq_passive_register_notifier(struct devfreq *devfreq)