1- // SPDX-License-Identifier: GPL-2.0-only
1+ // SPDX-License-Identifier: GPL-2.0-only
22/*
33 * linux/drivers/devfreq/governor_passive.c
44 *
1818
1919#define HZ_PER_KHZ 1000
2020
21+ static struct devfreq_cpu_data *
22+ get_parent_cpu_data (struct devfreq_passive_data * p_data ,
23+ struct cpufreq_policy * policy )
24+ {
25+ struct devfreq_cpu_data * parent_cpu_data ;
26+
27+ if (!p_data || !policy )
28+ return NULL ;
29+
30+ list_for_each_entry (parent_cpu_data , & p_data -> cpu_data_list , node )
31+ if (parent_cpu_data -> first_cpu == cpumask_first (policy -> related_cpus ))
32+ return parent_cpu_data ;
33+
34+ return NULL ;
35+ }
36+
2137static unsigned long get_target_freq_by_required_opp (struct device * p_dev ,
2238 struct opp_table * p_opp_table ,
2339 struct opp_table * opp_table ,
@@ -51,14 +67,24 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
5167 struct devfreq_passive_data * p_data =
5268 (struct devfreq_passive_data * )devfreq -> data ;
5369 struct devfreq_cpu_data * parent_cpu_data ;
70+ struct cpufreq_policy * policy ;
5471 unsigned long cpu , cpu_cur , cpu_min , cpu_max , cpu_percent ;
5572 unsigned long dev_min , dev_max ;
5673 unsigned long freq = 0 ;
74+ int ret = 0 ;
5775
5876 for_each_online_cpu (cpu ) {
59- parent_cpu_data = p_data -> parent_cpu_data [cpu ];
60- if (!parent_cpu_data || parent_cpu_data -> first_cpu != cpu )
77+ policy = cpufreq_cpu_get (cpu );
78+ if (!policy ) {
79+ ret = - EINVAL ;
80+ continue ;
81+ }
82+
83+ parent_cpu_data = get_parent_cpu_data (p_data , policy );
84+ if (!parent_cpu_data ) {
85+ cpufreq_cpu_put (policy );
6186 continue ;
87+ }
6288
6389 /* Get target freq via required opps */
6490 cpu_cur = parent_cpu_data -> cur_freq * HZ_PER_KHZ ;
@@ -67,6 +93,7 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
6793 devfreq -> opp_table , & cpu_cur );
6894 if (freq ) {
6995 * target_freq = max (freq , * target_freq );
96+ cpufreq_cpu_put (policy );
7097 continue ;
7198 }
7299
@@ -81,9 +108,10 @@ static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
81108 freq = dev_min + mult_frac (dev_max - dev_min , cpu_percent , 100 );
82109
83110 * target_freq = max (freq , * target_freq );
111+ cpufreq_cpu_put (policy );
84112 }
85113
86- return 0 ;
114+ return ret ;
87115}
88116
89117static int get_target_freq_with_devfreq (struct devfreq * devfreq ,
@@ -168,12 +196,11 @@ static int cpufreq_passive_notifier_call(struct notifier_block *nb,
168196 unsigned int cur_freq ;
169197 int ret ;
170198
171- if (event != CPUFREQ_POSTCHANGE || !freqs ||
172- !p_data -> parent_cpu_data [freqs -> policy -> cpu ])
199+ if (event != CPUFREQ_POSTCHANGE || !freqs )
173200 return 0 ;
174201
175- parent_cpu_data = p_data -> parent_cpu_data [ freqs -> policy -> cpu ] ;
176- if (parent_cpu_data -> cur_freq == freqs -> new )
202+ parent_cpu_data = get_parent_cpu_data ( p_data , freqs -> policy ) ;
203+ if (! parent_cpu_data || parent_cpu_data -> cur_freq == freqs -> new )
177204 return 0 ;
178205
179206 cur_freq = parent_cpu_data -> cur_freq ;
@@ -196,7 +223,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
196223 struct devfreq_passive_data * p_data
197224 = (struct devfreq_passive_data * )devfreq -> data ;
198225 struct devfreq_cpu_data * parent_cpu_data ;
199- int cpu , ret ;
226+ int cpu , ret = 0 ;
200227
201228 if (p_data -> nb .notifier_call ) {
202229 ret = cpufreq_unregister_notifier (& p_data -> nb ,
@@ -206,16 +233,26 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
206233 }
207234
208235 for_each_possible_cpu (cpu ) {
209- parent_cpu_data = p_data -> parent_cpu_data [cpu ];
210- if (!parent_cpu_data )
236+ struct cpufreq_policy * policy = cpufreq_cpu_get (cpu );
237+ if (!policy ) {
238+ ret = - EINVAL ;
211239 continue ;
240+ }
212241
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 );
213249 if (parent_cpu_data -> opp_table )
214250 dev_pm_opp_put_opp_table (parent_cpu_data -> opp_table );
215251 kfree (parent_cpu_data );
252+ cpufreq_cpu_put (policy );
216253 }
217254
218- return 0 ;
255+ return ret ;
219256}
220257
221258static int cpufreq_passive_register_notifier (struct devfreq * devfreq )
@@ -230,6 +267,9 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
230267 unsigned int cpu ;
231268 int ret ;
232269
270+ p_data -> cpu_data_list
271+ = (struct list_head )LIST_HEAD_INIT (p_data -> cpu_data_list );
272+
233273 p_data -> nb .notifier_call = cpufreq_passive_notifier_call ;
234274 ret = cpufreq_register_notifier (& p_data -> nb , CPUFREQ_TRANSITION_NOTIFIER );
235275 if (ret ) {
@@ -239,15 +279,18 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
239279 }
240280
241281 for_each_possible_cpu (cpu ) {
242- if (p_data -> parent_cpu_data [cpu ])
243- continue ;
244-
245282 policy = cpufreq_cpu_get (cpu );
246283 if (!policy ) {
247284 ret = - EPROBE_DEFER ;
248285 goto err ;
249286 }
250287
288+ parent_cpu_data = get_parent_cpu_data (p_data , policy );
289+ if (parent_cpu_data ) {
290+ cpufreq_cpu_put (policy );
291+ continue ;
292+ }
293+
251294 parent_cpu_data = kzalloc (sizeof (* parent_cpu_data ),
252295 GFP_KERNEL );
253296 if (!parent_cpu_data ) {
@@ -276,7 +319,7 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
276319 parent_cpu_data -> min_freq = policy -> cpuinfo .min_freq ;
277320 parent_cpu_data -> max_freq = policy -> cpuinfo .max_freq ;
278321
279- p_data -> parent_cpu_data [ cpu ] = parent_cpu_data ;
322+ list_add_tail ( & parent_cpu_data -> node , & p_data -> cpu_data_list ) ;
280323 cpufreq_cpu_put (policy );
281324 }
282325
0 commit comments