aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_governor.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-03-27 11:58:58 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-31 19:11:34 -0400
commit4d5dcc4211f9def4281eafb54b8ed483862e8135 (patch)
tree7f3c725675ce3042d2d2eb86b0b40f93cef73de3 /drivers/cpufreq/cpufreq_governor.c
parent7bd353a995d9049262661d85811d6109140582a3 (diff)
cpufreq: governor: Implement per policy instances of governors
Currently, there can't be multiple instances of single governor_type. If we have a multi-package system, where we have multiple instances of struct policy (per package), we can't have multiple instances of same governor. i.e. We can't have multiple instances of ondemand governor for multiple packages. Governors directory in sysfs is created at /sys/devices/system/cpu/cpufreq/ governor-name/. Which again reflects that there can be only one instance of a governor_type in the system. This is a bottleneck for multicluster system, where we want different packages to use same governor type, but with different tunables. This patch uses the infrastructure provided by earlier patch and implements init/exit routines for ondemand and conservative governors. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq_governor.c')
-rw-r--r--drivers/cpufreq/cpufreq_governor.c212
1 files changed, 142 insertions, 70 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 5a76086ff09b..26fbb729bc1c 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -22,12 +22,29 @@
22#include <linux/export.h> 22#include <linux/export.h>
23#include <linux/kernel_stat.h> 23#include <linux/kernel_stat.h>
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/slab.h>
25#include <linux/tick.h> 26#include <linux/tick.h>
26#include <linux/types.h> 27#include <linux/types.h>
27#include <linux/workqueue.h> 28#include <linux/workqueue.h>
28 29
29#include "cpufreq_governor.h" 30#include "cpufreq_governor.h"
30 31
32static struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
33{
34 if (have_governor_per_policy())
35 return &policy->kobj;
36 else
37 return cpufreq_global_kobject;
38}
39
40static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data)
41{
42 if (have_governor_per_policy())
43 return dbs_data->cdata->attr_group_gov_pol;
44 else
45 return dbs_data->cdata->attr_group_gov_sys;
46}
47
31static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) 48static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
32{ 49{
33 u64 idle_time; 50 u64 idle_time;
@@ -65,7 +82,7 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time);
65 82
66void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) 83void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
67{ 84{
68 struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu); 85 struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
69 struct od_dbs_tuners *od_tuners = dbs_data->tuners; 86 struct od_dbs_tuners *od_tuners = dbs_data->tuners;
70 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 87 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
71 struct cpufreq_policy *policy; 88 struct cpufreq_policy *policy;
@@ -73,7 +90,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
73 unsigned int ignore_nice; 90 unsigned int ignore_nice;
74 unsigned int j; 91 unsigned int j;
75 92
76 if (dbs_data->governor == GOV_ONDEMAND) 93 if (dbs_data->cdata->governor == GOV_ONDEMAND)
77 ignore_nice = od_tuners->ignore_nice; 94 ignore_nice = od_tuners->ignore_nice;
78 else 95 else
79 ignore_nice = cs_tuners->ignore_nice; 96 ignore_nice = cs_tuners->ignore_nice;
@@ -87,7 +104,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
87 unsigned int idle_time, wall_time, iowait_time; 104 unsigned int idle_time, wall_time, iowait_time;
88 unsigned int load; 105 unsigned int load;
89 106
90 j_cdbs = dbs_data->get_cpu_cdbs(j); 107 j_cdbs = dbs_data->cdata->get_cpu_cdbs(j);
91 108
92 cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); 109 cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
93 110
@@ -117,9 +134,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
117 idle_time += jiffies_to_usecs(cur_nice_jiffies); 134 idle_time += jiffies_to_usecs(cur_nice_jiffies);
118 } 135 }
119 136
120 if (dbs_data->governor == GOV_ONDEMAND) { 137 if (dbs_data->cdata->governor == GOV_ONDEMAND) {
121 struct od_cpu_dbs_info_s *od_j_dbs_info = 138 struct od_cpu_dbs_info_s *od_j_dbs_info =
122 dbs_data->get_cpu_dbs_info_s(cpu); 139 dbs_data->cdata->get_cpu_dbs_info_s(cpu);
123 140
124 cur_iowait_time = get_cpu_iowait_time_us(j, 141 cur_iowait_time = get_cpu_iowait_time_us(j,
125 &cur_wall_time); 142 &cur_wall_time);
@@ -145,7 +162,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
145 162
146 load = 100 * (wall_time - idle_time) / wall_time; 163 load = 100 * (wall_time - idle_time) / wall_time;
147 164
148 if (dbs_data->governor == GOV_ONDEMAND) { 165 if (dbs_data->cdata->governor == GOV_ONDEMAND) {
149 int freq_avg = __cpufreq_driver_getavg(policy, j); 166 int freq_avg = __cpufreq_driver_getavg(policy, j);
150 if (freq_avg <= 0) 167 if (freq_avg <= 0)
151 freq_avg = policy->cur; 168 freq_avg = policy->cur;
@@ -157,7 +174,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
157 max_load = load; 174 max_load = load;
158 } 175 }
159 176
160 dbs_data->gov_check_cpu(cpu, max_load); 177 dbs_data->cdata->gov_check_cpu(cpu, max_load);
161} 178}
162EXPORT_SYMBOL_GPL(dbs_check_cpu); 179EXPORT_SYMBOL_GPL(dbs_check_cpu);
163 180
@@ -165,14 +182,14 @@ static inline void dbs_timer_init(struct dbs_data *dbs_data, int cpu,
165 unsigned int sampling_rate) 182 unsigned int sampling_rate)
166{ 183{
167 int delay = delay_for_sampling_rate(sampling_rate); 184 int delay = delay_for_sampling_rate(sampling_rate);
168 struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu); 185 struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
169 186
170 schedule_delayed_work_on(cpu, &cdbs->work, delay); 187 schedule_delayed_work_on(cpu, &cdbs->work, delay);
171} 188}
172 189
173static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu) 190static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu)
174{ 191{
175 struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu); 192 struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
176 193
177 cancel_delayed_work_sync(&cdbs->work); 194 cancel_delayed_work_sync(&cdbs->work);
178} 195}
@@ -196,31 +213,128 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
196} 213}
197EXPORT_SYMBOL_GPL(need_load_eval); 214EXPORT_SYMBOL_GPL(need_load_eval);
198 215
199int cpufreq_governor_dbs(struct dbs_data *dbs_data, 216static void set_sampling_rate(struct dbs_data *dbs_data,
200 struct cpufreq_policy *policy, unsigned int event) 217 unsigned int sampling_rate)
218{
219 if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
220 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
221 cs_tuners->sampling_rate = sampling_rate;
222 } else {
223 struct od_dbs_tuners *od_tuners = dbs_data->tuners;
224 od_tuners->sampling_rate = sampling_rate;
225 }
226}
227
228int cpufreq_governor_dbs(struct cpufreq_policy *policy,
229 struct common_dbs_data *cdata, unsigned int event)
201{ 230{
231 struct dbs_data *dbs_data;
202 struct od_cpu_dbs_info_s *od_dbs_info = NULL; 232 struct od_cpu_dbs_info_s *od_dbs_info = NULL;
203 struct cs_cpu_dbs_info_s *cs_dbs_info = NULL; 233 struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
204 struct cs_ops *cs_ops = NULL;
205 struct od_ops *od_ops = NULL; 234 struct od_ops *od_ops = NULL;
206 struct od_dbs_tuners *od_tuners = dbs_data->tuners; 235 struct od_dbs_tuners *od_tuners = NULL;
207 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 236 struct cs_dbs_tuners *cs_tuners = NULL;
208 struct cpu_dbs_common_info *cpu_cdbs; 237 struct cpu_dbs_common_info *cpu_cdbs;
209 unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu; 238 unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
210 int rc; 239 int rc;
211 240
212 cpu_cdbs = dbs_data->get_cpu_cdbs(cpu); 241 if (have_governor_per_policy())
242 dbs_data = policy->governor_data;
243 else
244 dbs_data = cdata->gdbs_data;
245
246 WARN_ON(!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT));
247
248 switch (event) {
249 case CPUFREQ_GOV_POLICY_INIT:
250 if (have_governor_per_policy()) {
251 WARN_ON(dbs_data);
252 } else if (dbs_data) {
253 policy->governor_data = dbs_data;
254 return 0;
255 }
256
257 dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL);
258 if (!dbs_data) {
259 pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);
260 return -ENOMEM;
261 }
262
263 dbs_data->cdata = cdata;
264 rc = cdata->init(dbs_data);
265 if (rc) {
266 pr_err("%s: POLICY_INIT: init() failed\n", __func__);
267 kfree(dbs_data);
268 return rc;
269 }
270
271 rc = sysfs_create_group(get_governor_parent_kobj(policy),
272 get_sysfs_attr(dbs_data));
273 if (rc) {
274 cdata->exit(dbs_data);
275 kfree(dbs_data);
276 return rc;
277 }
278
279 policy->governor_data = dbs_data;
280
281 /* policy latency is in nS. Convert it to uS first */
282 latency = policy->cpuinfo.transition_latency / 1000;
283 if (latency == 0)
284 latency = 1;
285
286 /* Bring kernel and HW constraints together */
287 dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
288 MIN_LATENCY_MULTIPLIER * latency);
289 set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
290 latency * LATENCY_MULTIPLIER));
291
292 if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
293 struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
294
295 cpufreq_register_notifier(cs_ops->notifier_block,
296 CPUFREQ_TRANSITION_NOTIFIER);
297 }
298
299 if (!have_governor_per_policy())
300 cdata->gdbs_data = dbs_data;
301
302 return 0;
303 case CPUFREQ_GOV_POLICY_EXIT:
304 if ((policy->governor->initialized == 1) ||
305 have_governor_per_policy()) {
306 sysfs_remove_group(get_governor_parent_kobj(policy),
307 get_sysfs_attr(dbs_data));
308
309 if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
310 struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
311
312 cpufreq_unregister_notifier(cs_ops->notifier_block,
313 CPUFREQ_TRANSITION_NOTIFIER);
314 }
315
316 cdata->exit(dbs_data);
317 kfree(dbs_data);
318 cdata->gdbs_data = NULL;
319 }
213 320
214 if (dbs_data->governor == GOV_CONSERVATIVE) { 321 policy->governor_data = NULL;
215 cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu); 322 return 0;
216 sampling_rate = &cs_tuners->sampling_rate; 323 }
324
325 cpu_cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
326
327 if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
328 cs_tuners = dbs_data->tuners;
329 cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
330 sampling_rate = cs_tuners->sampling_rate;
217 ignore_nice = cs_tuners->ignore_nice; 331 ignore_nice = cs_tuners->ignore_nice;
218 cs_ops = dbs_data->gov_ops;
219 } else { 332 } else {
220 od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu); 333 od_tuners = dbs_data->tuners;
221 sampling_rate = &od_tuners->sampling_rate; 334 od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
335 sampling_rate = od_tuners->sampling_rate;
222 ignore_nice = od_tuners->ignore_nice; 336 ignore_nice = od_tuners->ignore_nice;
223 od_ops = dbs_data->gov_ops; 337 od_ops = dbs_data->cdata->gov_ops;
224 } 338 }
225 339
226 switch (event) { 340 switch (event) {
@@ -232,7 +346,7 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
232 346
233 for_each_cpu(j, policy->cpus) { 347 for_each_cpu(j, policy->cpus) {
234 struct cpu_dbs_common_info *j_cdbs = 348 struct cpu_dbs_common_info *j_cdbs =
235 dbs_data->get_cpu_cdbs(j); 349 dbs_data->cdata->get_cpu_cdbs(j);
236 350
237 j_cdbs->cpu = j; 351 j_cdbs->cpu = j;
238 j_cdbs->cur_policy = policy; 352 j_cdbs->cur_policy = policy;
@@ -244,69 +358,34 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
244 358
245 mutex_init(&j_cdbs->timer_mutex); 359 mutex_init(&j_cdbs->timer_mutex);
246 INIT_DEFERRABLE_WORK(&j_cdbs->work, 360 INIT_DEFERRABLE_WORK(&j_cdbs->work,
247 dbs_data->gov_dbs_timer); 361 dbs_data->cdata->gov_dbs_timer);
248 }
249
250 if (!policy->governor->initialized) {
251 rc = sysfs_create_group(cpufreq_global_kobject,
252 dbs_data->attr_group);
253 if (rc) {
254 mutex_unlock(&dbs_data->mutex);
255 return rc;
256 }
257 } 362 }
258 363
259 /* 364 /*
260 * conservative does not implement micro like ondemand 365 * conservative does not implement micro like ondemand
261 * governor, thus we are bound to jiffes/HZ 366 * governor, thus we are bound to jiffes/HZ
262 */ 367 */
263 if (dbs_data->governor == GOV_CONSERVATIVE) { 368 if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
264 cs_dbs_info->down_skip = 0; 369 cs_dbs_info->down_skip = 0;
265 cs_dbs_info->enable = 1; 370 cs_dbs_info->enable = 1;
266 cs_dbs_info->requested_freq = policy->cur; 371 cs_dbs_info->requested_freq = policy->cur;
267
268 if (!policy->governor->initialized) {
269 cpufreq_register_notifier(cs_ops->notifier_block,
270 CPUFREQ_TRANSITION_NOTIFIER);
271
272 dbs_data->min_sampling_rate =
273 MIN_SAMPLING_RATE_RATIO *
274 jiffies_to_usecs(10);
275 }
276 } else { 372 } else {
277 od_dbs_info->rate_mult = 1; 373 od_dbs_info->rate_mult = 1;
278 od_dbs_info->sample_type = OD_NORMAL_SAMPLE; 374 od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
279 od_ops->powersave_bias_init_cpu(cpu); 375 od_ops->powersave_bias_init_cpu(cpu);
280
281 if (!policy->governor->initialized)
282 od_tuners->io_is_busy = od_ops->io_busy();
283 } 376 }
284 377
285 if (policy->governor->initialized)
286 goto unlock;
287
288 /* policy latency is in nS. Convert it to uS first */
289 latency = policy->cpuinfo.transition_latency / 1000;
290 if (latency == 0)
291 latency = 1;
292
293 /* Bring kernel and HW constraints together */
294 dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
295 MIN_LATENCY_MULTIPLIER * latency);
296 *sampling_rate = max(dbs_data->min_sampling_rate, latency *
297 LATENCY_MULTIPLIER);
298unlock:
299 mutex_unlock(&dbs_data->mutex); 378 mutex_unlock(&dbs_data->mutex);
300 379
301 /* Initiate timer time stamp */ 380 /* Initiate timer time stamp */
302 cpu_cdbs->time_stamp = ktime_get(); 381 cpu_cdbs->time_stamp = ktime_get();
303 382
304 for_each_cpu(j, policy->cpus) 383 for_each_cpu(j, policy->cpus)
305 dbs_timer_init(dbs_data, j, *sampling_rate); 384 dbs_timer_init(dbs_data, j, sampling_rate);
306 break; 385 break;
307 386
308 case CPUFREQ_GOV_STOP: 387 case CPUFREQ_GOV_STOP:
309 if (dbs_data->governor == GOV_CONSERVATIVE) 388 if (dbs_data->cdata->governor == GOV_CONSERVATIVE)
310 cs_dbs_info->enable = 0; 389 cs_dbs_info->enable = 0;
311 390
312 for_each_cpu(j, policy->cpus) 391 for_each_cpu(j, policy->cpus)
@@ -315,13 +394,6 @@ unlock:
315 mutex_lock(&dbs_data->mutex); 394 mutex_lock(&dbs_data->mutex);
316 mutex_destroy(&cpu_cdbs->timer_mutex); 395 mutex_destroy(&cpu_cdbs->timer_mutex);
317 396
318 if (policy->governor->initialized == 1) {
319 sysfs_remove_group(cpufreq_global_kobject,
320 dbs_data->attr_group);
321 if (dbs_data->governor == GOV_CONSERVATIVE)
322 cpufreq_unregister_notifier(cs_ops->notifier_block,
323 CPUFREQ_TRANSITION_NOTIFIER);
324 }
325 mutex_unlock(&dbs_data->mutex); 397 mutex_unlock(&dbs_data->mutex);
326 398
327 break; 399 break;