Skip to content

Commit 0cca7e8

Browse files
Ansuelchanwoochoi
authored andcommitted
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: a03dacb ("PM / devfreq: Add cpu based scaling support to passive governor") Signed-off-by: Christian 'Ansuel' Marangi <[email protected]> Signed-off-by: Chanwoo Choi <[email protected]>
1 parent e52b045 commit 0cca7e8

File tree

1 file changed

+17
-22
lines changed

1 file changed

+17
-22
lines changed

drivers/devfreq/governor_passive.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,20 @@ get_parent_cpu_data(struct devfreq_passive_data *p_data,
3434
return NULL;
3535
}
3636

37+
static void delete_parent_cpu_data(struct devfreq_passive_data *p_data)
38+
{
39+
struct devfreq_cpu_data *parent_cpu_data, *tmp;
40+
41+
list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) {
42+
list_del(&parent_cpu_data->node);
43+
44+
if (parent_cpu_data->opp_table)
45+
dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
46+
47+
kfree(parent_cpu_data);
48+
}
49+
}
50+
3751
static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
3852
struct opp_table *p_opp_table,
3953
struct opp_table *opp_table,
@@ -222,8 +236,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
222236
{
223237
struct devfreq_passive_data *p_data
224238
= (struct devfreq_passive_data *)devfreq->data;
225-
struct devfreq_cpu_data *parent_cpu_data;
226-
int cpu, ret = 0;
239+
int ret;
227240

228241
if (p_data->nb.notifier_call) {
229242
ret = cpufreq_unregister_notifier(&p_data->nb,
@@ -232,27 +245,9 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
232245
return ret;
233246
}
234247

235-
for_each_possible_cpu(cpu) {
236-
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
237-
if (!policy) {
238-
ret = -EINVAL;
239-
continue;
240-
}
241-
242-
parent_cpu_data = get_parent_cpu_data(p_data, policy);
243-
if (!parent_cpu_data) {
244-
cpufreq_cpu_put(policy);
245-
continue;
246-
}
247-
248-
list_del(&parent_cpu_data->node);
249-
if (parent_cpu_data->opp_table)
250-
dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
251-
kfree(parent_cpu_data);
252-
cpufreq_cpu_put(policy);
253-
}
248+
delete_parent_cpu_data(p_data);
254249

255-
return ret;
250+
return 0;
256251
}
257252

258253
static int cpufreq_passive_register_notifier(struct devfreq *devfreq)

0 commit comments

Comments
 (0)