aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-06-13 17:33:49 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-06-13 17:33:49 -0400
commitd352cf47d93e39494b44b792cca8d35a3a0bd9b3 (patch)
tree90fd9360ed10da0eed160f84df423c9a687e4312
parentbb4b9933e2bc0554cf4db37aa07b19ff69a85f8f (diff)
cpufreq: conservative: Do not use transition notifications
The conservative governor registers a transition notifier so it can update its internal requested_freq value if it falls out of the policy->min...policy->max range, but requested_freq is not really necessary. That value is used to track the frequency requested by the governor previously, but policy->cur can be used instead of it and then the governor will not have to worry about updating the tracked value when the current frequency changes independently (for example, as a result of min or max changes). Accodringly, drop requested_freq from struct cs_policy_dbs_info and modify cs_dbs_timer() to use policy->cur instead of it. While at it, notice that __cpufreq_driver_target() clamps its target_freq argument between policy->min and policy->max, so the callers of it don't have to do that and make additional changes in cs_dbs_timer() in accordance with that. After these changes the transition notifier used by the conservative governor is not necessary any more, so drop it, which also makes it possible to drop the struct cs_governor definition and simplify the code accordingly. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c103
1 files changed, 21 insertions, 82 deletions
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index f967ec6c5720..18da4f8051d3 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -17,7 +17,6 @@
17struct cs_policy_dbs_info { 17struct cs_policy_dbs_info {
18 struct policy_dbs_info policy_dbs; 18 struct policy_dbs_info policy_dbs;
19 unsigned int down_skip; 19 unsigned int down_skip;
20 unsigned int requested_freq;
21}; 20};
22 21
23static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 22static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
@@ -75,19 +74,17 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
75 74
76 /* Check for frequency increase */ 75 /* Check for frequency increase */
77 if (load > dbs_data->up_threshold) { 76 if (load > dbs_data->up_threshold) {
77 unsigned int requested_freq = policy->cur;
78
78 dbs_info->down_skip = 0; 79 dbs_info->down_skip = 0;
79 80
80 /* if we are already at full speed then break out early */ 81 /* if we are already at full speed then break out early */
81 if (dbs_info->requested_freq == policy->max) 82 if (requested_freq == policy->max)
82 goto out; 83 goto out;
83 84
84 dbs_info->requested_freq += get_freq_target(cs_tuners, policy); 85 requested_freq += get_freq_target(cs_tuners, policy);
85
86 if (dbs_info->requested_freq > policy->max)
87 dbs_info->requested_freq = policy->max;
88 86
89 __cpufreq_driver_target(policy, dbs_info->requested_freq, 87 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
90 CPUFREQ_RELATION_H);
91 goto out; 88 goto out;
92 } 89 }
93 90
@@ -98,34 +95,26 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
98 95
99 /* Check for frequency decrease */ 96 /* Check for frequency decrease */
100 if (load < cs_tuners->down_threshold) { 97 if (load < cs_tuners->down_threshold) {
101 unsigned int freq_target; 98 unsigned int freq_target, requested_freq = policy->cur;
102 /* 99 /*
103 * if we cannot reduce the frequency anymore, break out early 100 * if we cannot reduce the frequency anymore, break out early
104 */ 101 */
105 if (policy->cur == policy->min) 102 if (requested_freq == policy->min)
106 goto out; 103 goto out;
107 104
108 freq_target = get_freq_target(cs_tuners, policy); 105 freq_target = get_freq_target(cs_tuners, policy);
109 if (dbs_info->requested_freq > freq_target) 106 if (requested_freq > freq_target)
110 dbs_info->requested_freq -= freq_target; 107 requested_freq -= freq_target;
111 else 108 else
112 dbs_info->requested_freq = policy->min; 109 requested_freq = policy->min;
113 110
114 __cpufreq_driver_target(policy, dbs_info->requested_freq, 111 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
115 CPUFREQ_RELATION_L);
116 } 112 }
117 113
118 out: 114 out:
119 return dbs_data->sampling_rate; 115 return dbs_data->sampling_rate;
120} 116}
121 117
122static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
123 void *data);
124
125static struct notifier_block cs_cpufreq_notifier_block = {
126 .notifier_call = dbs_cpufreq_notifier,
127};
128
129/************************** sysfs interface ************************/ 118/************************** sysfs interface ************************/
130 119
131static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, 120static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
@@ -254,13 +243,6 @@ static struct attribute *cs_attributes[] = {
254 243
255/************************** sysfs end ************************/ 244/************************** sysfs end ************************/
256 245
257struct cs_governor {
258 struct dbs_governor dbs_gov;
259 unsigned int usage_count;
260};
261
262static struct cs_governor cs_gov;
263
264static struct policy_dbs_info *cs_alloc(void) 246static struct policy_dbs_info *cs_alloc(void)
265{ 247{
266 struct cs_policy_dbs_info *dbs_info; 248 struct cs_policy_dbs_info *dbs_info;
@@ -292,25 +274,11 @@ static int cs_init(struct dbs_data *dbs_data)
292 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * 274 dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
293 jiffies_to_usecs(10); 275 jiffies_to_usecs(10);
294 276
295 /*
296 * This function and cs_exit() are only called under gov_dbs_data_mutex
297 * which is global, so the cs_gov.usage_count accesses are guaranteed
298 * to be serialized.
299 */
300 if (!cs_gov.usage_count++)
301 cpufreq_register_notifier(&cs_cpufreq_notifier_block,
302 CPUFREQ_TRANSITION_NOTIFIER);
303
304 return 0; 277 return 0;
305} 278}
306 279
307static void cs_exit(struct dbs_data *dbs_data) 280static void cs_exit(struct dbs_data *dbs_data)
308{ 281{
309 /* Protected by gov_dbs_data_mutex - see the comment in cs_init(). */
310 if (!--cs_gov.usage_count)
311 cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
312 CPUFREQ_TRANSITION_NOTIFIER);
313
314 kfree(dbs_data->tuners); 282 kfree(dbs_data->tuners);
315} 283}
316 284
@@ -319,49 +287,20 @@ static void cs_start(struct cpufreq_policy *policy)
319 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); 287 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
320 288
321 dbs_info->down_skip = 0; 289 dbs_info->down_skip = 0;
322 dbs_info->requested_freq = policy->cur;
323} 290}
324 291
325static struct cs_governor cs_gov = { 292static struct dbs_governor cs_governor = {
326 .dbs_gov = { 293 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
327 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"), 294 .kobj_type = { .default_attrs = cs_attributes },
328 .kobj_type = { .default_attrs = cs_attributes }, 295 .gov_dbs_timer = cs_dbs_timer,
329 .gov_dbs_timer = cs_dbs_timer, 296 .alloc = cs_alloc,
330 .alloc = cs_alloc, 297 .free = cs_free,
331 .free = cs_free, 298 .init = cs_init,
332 .init = cs_init, 299 .exit = cs_exit,
333 .exit = cs_exit, 300 .start = cs_start,
334 .start = cs_start,
335 },
336}; 301};
337 302
338#define CPU_FREQ_GOV_CONSERVATIVE (&cs_gov.dbs_gov.gov) 303#define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.gov)
339
340static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
341 void *data)
342{
343 struct cpufreq_freqs *freq = data;
344 struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
345 struct cs_policy_dbs_info *dbs_info;
346
347 if (!policy)
348 return 0;
349
350 /* policy isn't governed by conservative governor */
351 if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
352 return 0;
353
354 dbs_info = to_dbs_info(policy->governor_data);
355 /*
356 * we only care if our internally tracked freq moves outside the 'valid'
357 * ranges of frequency available to us otherwise we do not change it
358 */
359 if (dbs_info->requested_freq > policy->max
360 || dbs_info->requested_freq < policy->min)
361 dbs_info->requested_freq = freq->new;
362
363 return 0;
364}
365 304
366static int __init cpufreq_gov_dbs_init(void) 305static int __init cpufreq_gov_dbs_init(void)
367{ 306{