diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq_ondemand.c')
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 266 |
1 files changed, 96 insertions, 170 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 693e540481b4..52cf1f021825 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -12,22 +12,11 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/smp.h> | ||
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/cpufreq.h> | 16 | #include <linux/cpufreq.h> |
20 | #include <linux/sysctl.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/sysfs.h> | ||
24 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
25 | #include <linux/sched.h> | ||
26 | #include <linux/kmod.h> | ||
27 | #include <linux/workqueue.h> | ||
28 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
29 | #include <linux/kernel_stat.h> | 19 | #include <linux/kernel_stat.h> |
30 | #include <linux/percpu.h> | ||
31 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
32 | 21 | ||
33 | /* | 22 | /* |
@@ -56,16 +45,15 @@ static unsigned int def_sampling_rate; | |||
56 | #define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) | 45 | #define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) |
57 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) | 46 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) |
58 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) | 47 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) |
59 | #define DEF_SAMPLING_DOWN_FACTOR (1) | ||
60 | #define MAX_SAMPLING_DOWN_FACTOR (10) | ||
61 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) | 48 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) |
62 | 49 | ||
63 | static void do_dbs_timer(void *data); | 50 | static void do_dbs_timer(void *data); |
64 | 51 | ||
65 | struct cpu_dbs_info_s { | 52 | struct cpu_dbs_info_s { |
53 | cputime64_t prev_cpu_idle; | ||
54 | cputime64_t prev_cpu_wall; | ||
66 | struct cpufreq_policy *cur_policy; | 55 | struct cpufreq_policy *cur_policy; |
67 | unsigned int prev_cpu_idle_up; | 56 | struct work_struct work; |
68 | unsigned int prev_cpu_idle_down; | ||
69 | unsigned int enable; | 57 | unsigned int enable; |
70 | }; | 58 | }; |
71 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 59 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
@@ -80,31 +68,32 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ | |||
80 | * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock | 68 | * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock |
81 | * is recursive for the same process. -Venki | 69 | * is recursive for the same process. -Venki |
82 | */ | 70 | */ |
83 | static DEFINE_MUTEX (dbs_mutex); | 71 | static DEFINE_MUTEX(dbs_mutex); |
84 | static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); | ||
85 | 72 | ||
86 | static struct workqueue_struct *dbs_workq; | 73 | static struct workqueue_struct *kondemand_wq; |
87 | 74 | ||
88 | struct dbs_tuners { | 75 | struct dbs_tuners { |
89 | unsigned int sampling_rate; | 76 | unsigned int sampling_rate; |
90 | unsigned int sampling_down_factor; | ||
91 | unsigned int up_threshold; | 77 | unsigned int up_threshold; |
92 | unsigned int ignore_nice; | 78 | unsigned int ignore_nice; |
93 | }; | 79 | }; |
94 | 80 | ||
95 | static struct dbs_tuners dbs_tuners_ins = { | 81 | static struct dbs_tuners dbs_tuners_ins = { |
96 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 82 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
97 | .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, | ||
98 | .ignore_nice = 0, | 83 | .ignore_nice = 0, |
99 | }; | 84 | }; |
100 | 85 | ||
101 | static inline unsigned int get_cpu_idle_time(unsigned int cpu) | 86 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu) |
102 | { | 87 | { |
103 | return kstat_cpu(cpu).cpustat.idle + | 88 | cputime64_t retval; |
104 | kstat_cpu(cpu).cpustat.iowait + | 89 | |
105 | ( dbs_tuners_ins.ignore_nice ? | 90 | retval = cputime64_add(kstat_cpu(cpu).cpustat.idle, |
106 | kstat_cpu(cpu).cpustat.nice : | 91 | kstat_cpu(cpu).cpustat.iowait); |
107 | 0); | 92 | |
93 | if (dbs_tuners_ins.ignore_nice) | ||
94 | retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice); | ||
95 | |||
96 | return retval; | ||
108 | } | 97 | } |
109 | 98 | ||
110 | /************************** sysfs interface ************************/ | 99 | /************************** sysfs interface ************************/ |
@@ -133,35 +122,15 @@ static ssize_t show_##file_name \ | |||
133 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | 122 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ |
134 | } | 123 | } |
135 | show_one(sampling_rate, sampling_rate); | 124 | show_one(sampling_rate, sampling_rate); |
136 | show_one(sampling_down_factor, sampling_down_factor); | ||
137 | show_one(up_threshold, up_threshold); | 125 | show_one(up_threshold, up_threshold); |
138 | show_one(ignore_nice_load, ignore_nice); | 126 | show_one(ignore_nice_load, ignore_nice); |
139 | 127 | ||
140 | static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, | ||
141 | const char *buf, size_t count) | ||
142 | { | ||
143 | unsigned int input; | ||
144 | int ret; | ||
145 | ret = sscanf (buf, "%u", &input); | ||
146 | if (ret != 1 ) | ||
147 | return -EINVAL; | ||
148 | |||
149 | if (input > MAX_SAMPLING_DOWN_FACTOR || input < 1) | ||
150 | return -EINVAL; | ||
151 | |||
152 | mutex_lock(&dbs_mutex); | ||
153 | dbs_tuners_ins.sampling_down_factor = input; | ||
154 | mutex_unlock(&dbs_mutex); | ||
155 | |||
156 | return count; | ||
157 | } | ||
158 | |||
159 | static ssize_t store_sampling_rate(struct cpufreq_policy *unused, | 128 | static ssize_t store_sampling_rate(struct cpufreq_policy *unused, |
160 | const char *buf, size_t count) | 129 | const char *buf, size_t count) |
161 | { | 130 | { |
162 | unsigned int input; | 131 | unsigned int input; |
163 | int ret; | 132 | int ret; |
164 | ret = sscanf (buf, "%u", &input); | 133 | ret = sscanf(buf, "%u", &input); |
165 | 134 | ||
166 | mutex_lock(&dbs_mutex); | 135 | mutex_lock(&dbs_mutex); |
167 | if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { | 136 | if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { |
@@ -180,7 +149,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, | |||
180 | { | 149 | { |
181 | unsigned int input; | 150 | unsigned int input; |
182 | int ret; | 151 | int ret; |
183 | ret = sscanf (buf, "%u", &input); | 152 | ret = sscanf(buf, "%u", &input); |
184 | 153 | ||
185 | mutex_lock(&dbs_mutex); | 154 | mutex_lock(&dbs_mutex); |
186 | if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || | 155 | if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || |
@@ -203,7 +172,7 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, | |||
203 | 172 | ||
204 | unsigned int j; | 173 | unsigned int j; |
205 | 174 | ||
206 | ret = sscanf (buf, "%u", &input); | 175 | ret = sscanf(buf, "%u", &input); |
207 | if ( ret != 1 ) | 176 | if ( ret != 1 ) |
208 | return -EINVAL; | 177 | return -EINVAL; |
209 | 178 | ||
@@ -217,12 +186,12 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, | |||
217 | } | 186 | } |
218 | dbs_tuners_ins.ignore_nice = input; | 187 | dbs_tuners_ins.ignore_nice = input; |
219 | 188 | ||
220 | /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ | 189 | /* we need to re-evaluate prev_cpu_idle */ |
221 | for_each_online_cpu(j) { | 190 | for_each_online_cpu(j) { |
222 | struct cpu_dbs_info_s *j_dbs_info; | 191 | struct cpu_dbs_info_s *dbs_info; |
223 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 192 | dbs_info = &per_cpu(cpu_dbs_info, j); |
224 | j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); | 193 | dbs_info->prev_cpu_idle = get_cpu_idle_time(j); |
225 | j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; | 194 | dbs_info->prev_cpu_wall = get_jiffies_64(); |
226 | } | 195 | } |
227 | mutex_unlock(&dbs_mutex); | 196 | mutex_unlock(&dbs_mutex); |
228 | 197 | ||
@@ -234,7 +203,6 @@ static struct freq_attr _name = \ | |||
234 | __ATTR(_name, 0644, show_##_name, store_##_name) | 203 | __ATTR(_name, 0644, show_##_name, store_##_name) |
235 | 204 | ||
236 | define_one_rw(sampling_rate); | 205 | define_one_rw(sampling_rate); |
237 | define_one_rw(sampling_down_factor); | ||
238 | define_one_rw(up_threshold); | 206 | define_one_rw(up_threshold); |
239 | define_one_rw(ignore_nice_load); | 207 | define_one_rw(ignore_nice_load); |
240 | 208 | ||
@@ -242,7 +210,6 @@ static struct attribute * dbs_attributes[] = { | |||
242 | &sampling_rate_max.attr, | 210 | &sampling_rate_max.attr, |
243 | &sampling_rate_min.attr, | 211 | &sampling_rate_min.attr, |
244 | &sampling_rate.attr, | 212 | &sampling_rate.attr, |
245 | &sampling_down_factor.attr, | ||
246 | &up_threshold.attr, | 213 | &up_threshold.attr, |
247 | &ignore_nice_load.attr, | 214 | &ignore_nice_load.attr, |
248 | NULL | 215 | NULL |
@@ -255,26 +222,29 @@ static struct attribute_group dbs_attr_group = { | |||
255 | 222 | ||
256 | /************************** sysfs end ************************/ | 223 | /************************** sysfs end ************************/ |
257 | 224 | ||
258 | static void dbs_check_cpu(int cpu) | 225 | static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) |
259 | { | 226 | { |
260 | unsigned int idle_ticks, up_idle_ticks, total_ticks; | 227 | unsigned int idle_ticks, total_ticks; |
261 | unsigned int freq_next; | 228 | unsigned int load; |
262 | unsigned int freq_down_sampling_rate; | 229 | cputime64_t cur_jiffies; |
263 | static int down_skip[NR_CPUS]; | ||
264 | struct cpu_dbs_info_s *this_dbs_info; | ||
265 | 230 | ||
266 | struct cpufreq_policy *policy; | 231 | struct cpufreq_policy *policy; |
267 | unsigned int j; | 232 | unsigned int j; |
268 | 233 | ||
269 | this_dbs_info = &per_cpu(cpu_dbs_info, cpu); | ||
270 | if (!this_dbs_info->enable) | 234 | if (!this_dbs_info->enable) |
271 | return; | 235 | return; |
272 | 236 | ||
273 | policy = this_dbs_info->cur_policy; | 237 | policy = this_dbs_info->cur_policy; |
238 | cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); | ||
239 | total_ticks = (unsigned int) cputime64_sub(cur_jiffies, | ||
240 | this_dbs_info->prev_cpu_wall); | ||
241 | this_dbs_info->prev_cpu_wall = cur_jiffies; | ||
242 | if (!total_ticks) | ||
243 | return; | ||
274 | /* | 244 | /* |
275 | * Every sampling_rate, we check, if current idle time is less | 245 | * Every sampling_rate, we check, if current idle time is less |
276 | * than 20% (default), then we try to increase frequency | 246 | * than 20% (default), then we try to increase frequency |
277 | * Every sampling_rate*sampling_down_factor, we look for a the lowest | 247 | * Every sampling_rate, we look for a the lowest |
278 | * frequency which can sustain the load while keeping idle time over | 248 | * frequency which can sustain the load while keeping idle time over |
279 | * 30%. If such a frequency exist, we try to decrease to this frequency. | 249 | * 30%. If such a frequency exist, we try to decrease to this frequency. |
280 | * | 250 | * |
@@ -283,36 +253,26 @@ static void dbs_check_cpu(int cpu) | |||
283 | * 5% (default) of current frequency | 253 | * 5% (default) of current frequency |
284 | */ | 254 | */ |
285 | 255 | ||
286 | /* Check for frequency increase */ | 256 | /* Get Idle Time */ |
287 | idle_ticks = UINT_MAX; | 257 | idle_ticks = UINT_MAX; |
288 | for_each_cpu_mask(j, policy->cpus) { | 258 | for_each_cpu_mask(j, policy->cpus) { |
289 | unsigned int tmp_idle_ticks, total_idle_ticks; | 259 | cputime64_t total_idle_ticks; |
260 | unsigned int tmp_idle_ticks; | ||
290 | struct cpu_dbs_info_s *j_dbs_info; | 261 | struct cpu_dbs_info_s *j_dbs_info; |
291 | 262 | ||
292 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 263 | j_dbs_info = &per_cpu(cpu_dbs_info, j); |
293 | total_idle_ticks = get_cpu_idle_time(j); | 264 | total_idle_ticks = get_cpu_idle_time(j); |
294 | tmp_idle_ticks = total_idle_ticks - | 265 | tmp_idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks, |
295 | j_dbs_info->prev_cpu_idle_up; | 266 | j_dbs_info->prev_cpu_idle); |
296 | j_dbs_info->prev_cpu_idle_up = total_idle_ticks; | 267 | j_dbs_info->prev_cpu_idle = total_idle_ticks; |
297 | 268 | ||
298 | if (tmp_idle_ticks < idle_ticks) | 269 | if (tmp_idle_ticks < idle_ticks) |
299 | idle_ticks = tmp_idle_ticks; | 270 | idle_ticks = tmp_idle_ticks; |
300 | } | 271 | } |
272 | load = (100 * (total_ticks - idle_ticks)) / total_ticks; | ||
301 | 273 | ||
302 | /* Scale idle ticks by 100 and compare with up and down ticks */ | 274 | /* Check for frequency increase */ |
303 | idle_ticks *= 100; | 275 | if (load > dbs_tuners_ins.up_threshold) { |
304 | up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * | ||
305 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
306 | |||
307 | if (idle_ticks < up_idle_ticks) { | ||
308 | down_skip[cpu] = 0; | ||
309 | for_each_cpu_mask(j, policy->cpus) { | ||
310 | struct cpu_dbs_info_s *j_dbs_info; | ||
311 | |||
312 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | ||
313 | j_dbs_info->prev_cpu_idle_down = | ||
314 | j_dbs_info->prev_cpu_idle_up; | ||
315 | } | ||
316 | /* if we are already at full speed then break out early */ | 276 | /* if we are already at full speed then break out early */ |
317 | if (policy->cur == policy->max) | 277 | if (policy->cur == policy->max) |
318 | return; | 278 | return; |
@@ -323,83 +283,54 @@ static void dbs_check_cpu(int cpu) | |||
323 | } | 283 | } |
324 | 284 | ||
325 | /* Check for frequency decrease */ | 285 | /* Check for frequency decrease */ |
326 | down_skip[cpu]++; | ||
327 | if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) | ||
328 | return; | ||
329 | |||
330 | idle_ticks = UINT_MAX; | ||
331 | for_each_cpu_mask(j, policy->cpus) { | ||
332 | unsigned int tmp_idle_ticks, total_idle_ticks; | ||
333 | struct cpu_dbs_info_s *j_dbs_info; | ||
334 | |||
335 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | ||
336 | /* Check for frequency decrease */ | ||
337 | total_idle_ticks = j_dbs_info->prev_cpu_idle_up; | ||
338 | tmp_idle_ticks = total_idle_ticks - | ||
339 | j_dbs_info->prev_cpu_idle_down; | ||
340 | j_dbs_info->prev_cpu_idle_down = total_idle_ticks; | ||
341 | |||
342 | if (tmp_idle_ticks < idle_ticks) | ||
343 | idle_ticks = tmp_idle_ticks; | ||
344 | } | ||
345 | |||
346 | down_skip[cpu] = 0; | ||
347 | /* if we cannot reduce the frequency anymore, break out early */ | 286 | /* if we cannot reduce the frequency anymore, break out early */ |
348 | if (policy->cur == policy->min) | 287 | if (policy->cur == policy->min) |
349 | return; | 288 | return; |
350 | 289 | ||
351 | /* Compute how many ticks there are between two measurements */ | ||
352 | freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * | ||
353 | dbs_tuners_ins.sampling_down_factor; | ||
354 | total_ticks = usecs_to_jiffies(freq_down_sampling_rate); | ||
355 | |||
356 | /* | 290 | /* |
357 | * The optimal frequency is the frequency that is the lowest that | 291 | * The optimal frequency is the frequency that is the lowest that |
358 | * can support the current CPU usage without triggering the up | 292 | * can support the current CPU usage without triggering the up |
359 | * policy. To be safe, we focus 10 points under the threshold. | 293 | * policy. To be safe, we focus 10 points under the threshold. |
360 | */ | 294 | */ |
361 | freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks; | 295 | if (load < (dbs_tuners_ins.up_threshold - 10)) { |
362 | freq_next = (freq_next * policy->cur) / | 296 | unsigned int freq_next; |
297 | freq_next = (policy->cur * load) / | ||
363 | (dbs_tuners_ins.up_threshold - 10); | 298 | (dbs_tuners_ins.up_threshold - 10); |
364 | 299 | ||
365 | if (freq_next < policy->min) | ||
366 | freq_next = policy->min; | ||
367 | |||
368 | if (freq_next <= ((policy->cur * 95) / 100)) | ||
369 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); | 300 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); |
301 | } | ||
370 | } | 302 | } |
371 | 303 | ||
372 | static void do_dbs_timer(void *data) | 304 | static void do_dbs_timer(void *data) |
373 | { | 305 | { |
374 | int i; | 306 | unsigned int cpu = smp_processor_id(); |
307 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); | ||
308 | |||
309 | if (!dbs_info->enable) | ||
310 | return; | ||
311 | |||
375 | lock_cpu_hotplug(); | 312 | lock_cpu_hotplug(); |
376 | mutex_lock(&dbs_mutex); | 313 | dbs_check_cpu(dbs_info); |
377 | for_each_online_cpu(i) | ||
378 | dbs_check_cpu(i); | ||
379 | queue_delayed_work(dbs_workq, &dbs_work, | ||
380 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); | ||
381 | mutex_unlock(&dbs_mutex); | ||
382 | unlock_cpu_hotplug(); | 314 | unlock_cpu_hotplug(); |
315 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, | ||
316 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); | ||
383 | } | 317 | } |
384 | 318 | ||
385 | static inline void dbs_timer_init(void) | 319 | static inline void dbs_timer_init(unsigned int cpu) |
386 | { | 320 | { |
387 | INIT_WORK(&dbs_work, do_dbs_timer, NULL); | 321 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); |
388 | if (!dbs_workq) | 322 | |
389 | dbs_workq = create_singlethread_workqueue("ondemand"); | 323 | INIT_WORK(&dbs_info->work, do_dbs_timer, 0); |
390 | if (!dbs_workq) { | 324 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, |
391 | printk(KERN_ERR "ondemand: Cannot initialize kernel thread\n"); | 325 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); |
392 | return; | ||
393 | } | ||
394 | queue_delayed_work(dbs_workq, &dbs_work, | ||
395 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); | ||
396 | return; | 326 | return; |
397 | } | 327 | } |
398 | 328 | ||
399 | static inline void dbs_timer_exit(void) | 329 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) |
400 | { | 330 | { |
401 | if (dbs_workq) | 331 | dbs_info->enable = 0; |
402 | cancel_rearming_delayed_workqueue(dbs_workq, &dbs_work); | 332 | cancel_delayed_work(&dbs_info->work); |
333 | flush_workqueue(kondemand_wq); | ||
403 | } | 334 | } |
404 | 335 | ||
405 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | 336 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, |
@@ -413,8 +344,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
413 | 344 | ||
414 | switch (event) { | 345 | switch (event) { |
415 | case CPUFREQ_GOV_START: | 346 | case CPUFREQ_GOV_START: |
416 | if ((!cpu_online(cpu)) || | 347 | if ((!cpu_online(cpu)) || (!policy->cur)) |
417 | (!policy->cur)) | ||
418 | return -EINVAL; | 348 | return -EINVAL; |
419 | 349 | ||
420 | if (policy->cpuinfo.transition_latency > | 350 | if (policy->cpuinfo.transition_latency > |
@@ -427,18 +357,26 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
427 | break; | 357 | break; |
428 | 358 | ||
429 | mutex_lock(&dbs_mutex); | 359 | mutex_lock(&dbs_mutex); |
360 | dbs_enable++; | ||
361 | if (dbs_enable == 1) { | ||
362 | kondemand_wq = create_workqueue("kondemand"); | ||
363 | if (!kondemand_wq) { | ||
364 | printk(KERN_ERR "Creation of kondemand failed\n"); | ||
365 | dbs_enable--; | ||
366 | mutex_unlock(&dbs_mutex); | ||
367 | return -ENOSPC; | ||
368 | } | ||
369 | } | ||
430 | for_each_cpu_mask(j, policy->cpus) { | 370 | for_each_cpu_mask(j, policy->cpus) { |
431 | struct cpu_dbs_info_s *j_dbs_info; | 371 | struct cpu_dbs_info_s *j_dbs_info; |
432 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 372 | j_dbs_info = &per_cpu(cpu_dbs_info, j); |
433 | j_dbs_info->cur_policy = policy; | 373 | j_dbs_info->cur_policy = policy; |
434 | 374 | ||
435 | j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); | 375 | j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j); |
436 | j_dbs_info->prev_cpu_idle_down | 376 | j_dbs_info->prev_cpu_wall = get_jiffies_64(); |
437 | = j_dbs_info->prev_cpu_idle_up; | ||
438 | } | 377 | } |
439 | this_dbs_info->enable = 1; | 378 | this_dbs_info->enable = 1; |
440 | sysfs_create_group(&policy->kobj, &dbs_attr_group); | 379 | sysfs_create_group(&policy->kobj, &dbs_attr_group); |
441 | dbs_enable++; | ||
442 | /* | 380 | /* |
443 | * Start the timerschedule work, when this governor | 381 | * Start the timerschedule work, when this governor |
444 | * is used for first time | 382 | * is used for first time |
@@ -457,50 +395,44 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
457 | def_sampling_rate = MIN_STAT_SAMPLING_RATE; | 395 | def_sampling_rate = MIN_STAT_SAMPLING_RATE; |
458 | 396 | ||
459 | dbs_tuners_ins.sampling_rate = def_sampling_rate; | 397 | dbs_tuners_ins.sampling_rate = def_sampling_rate; |
460 | dbs_timer_init(); | ||
461 | } | 398 | } |
399 | dbs_timer_init(policy->cpu); | ||
462 | 400 | ||
463 | mutex_unlock(&dbs_mutex); | 401 | mutex_unlock(&dbs_mutex); |
464 | break; | 402 | break; |
465 | 403 | ||
466 | case CPUFREQ_GOV_STOP: | 404 | case CPUFREQ_GOV_STOP: |
467 | mutex_lock(&dbs_mutex); | 405 | mutex_lock(&dbs_mutex); |
468 | this_dbs_info->enable = 0; | 406 | dbs_timer_exit(this_dbs_info); |
469 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); | 407 | sysfs_remove_group(&policy->kobj, &dbs_attr_group); |
470 | dbs_enable--; | 408 | dbs_enable--; |
471 | /* | ||
472 | * Stop the timerschedule work, when this governor | ||
473 | * is used for first time | ||
474 | */ | ||
475 | if (dbs_enable == 0) | 409 | if (dbs_enable == 0) |
476 | dbs_timer_exit(); | 410 | destroy_workqueue(kondemand_wq); |
477 | 411 | ||
478 | mutex_unlock(&dbs_mutex); | 412 | mutex_unlock(&dbs_mutex); |
479 | 413 | ||
480 | break; | 414 | break; |
481 | 415 | ||
482 | case CPUFREQ_GOV_LIMITS: | 416 | case CPUFREQ_GOV_LIMITS: |
483 | lock_cpu_hotplug(); | ||
484 | mutex_lock(&dbs_mutex); | 417 | mutex_lock(&dbs_mutex); |
485 | if (policy->max < this_dbs_info->cur_policy->cur) | 418 | if (policy->max < this_dbs_info->cur_policy->cur) |
486 | __cpufreq_driver_target( | 419 | __cpufreq_driver_target(this_dbs_info->cur_policy, |
487 | this_dbs_info->cur_policy, | 420 | policy->max, |
488 | policy->max, CPUFREQ_RELATION_H); | 421 | CPUFREQ_RELATION_H); |
489 | else if (policy->min > this_dbs_info->cur_policy->cur) | 422 | else if (policy->min > this_dbs_info->cur_policy->cur) |
490 | __cpufreq_driver_target( | 423 | __cpufreq_driver_target(this_dbs_info->cur_policy, |
491 | this_dbs_info->cur_policy, | 424 | policy->min, |
492 | policy->min, CPUFREQ_RELATION_L); | 425 | CPUFREQ_RELATION_L); |
493 | mutex_unlock(&dbs_mutex); | 426 | mutex_unlock(&dbs_mutex); |
494 | unlock_cpu_hotplug(); | ||
495 | break; | 427 | break; |
496 | } | 428 | } |
497 | return 0; | 429 | return 0; |
498 | } | 430 | } |
499 | 431 | ||
500 | static struct cpufreq_governor cpufreq_gov_dbs = { | 432 | static struct cpufreq_governor cpufreq_gov_dbs = { |
501 | .name = "ondemand", | 433 | .name = "ondemand", |
502 | .governor = cpufreq_governor_dbs, | 434 | .governor = cpufreq_governor_dbs, |
503 | .owner = THIS_MODULE, | 435 | .owner = THIS_MODULE, |
504 | }; | 436 | }; |
505 | 437 | ||
506 | static int __init cpufreq_gov_dbs_init(void) | 438 | static int __init cpufreq_gov_dbs_init(void) |
@@ -510,21 +442,15 @@ static int __init cpufreq_gov_dbs_init(void) | |||
510 | 442 | ||
511 | static void __exit cpufreq_gov_dbs_exit(void) | 443 | static void __exit cpufreq_gov_dbs_exit(void) |
512 | { | 444 | { |
513 | /* Make sure that the scheduled work is indeed not running. | ||
514 | Assumes the timer has been cancelled first. */ | ||
515 | if (dbs_workq) { | ||
516 | flush_workqueue(dbs_workq); | ||
517 | destroy_workqueue(dbs_workq); | ||
518 | } | ||
519 | |||
520 | cpufreq_unregister_governor(&cpufreq_gov_dbs); | 445 | cpufreq_unregister_governor(&cpufreq_gov_dbs); |
521 | } | 446 | } |
522 | 447 | ||
523 | 448 | ||
524 | MODULE_AUTHOR ("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>"); | 449 | MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>"); |
525 | MODULE_DESCRIPTION ("'cpufreq_ondemand' - A dynamic cpufreq governor for " | 450 | MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>"); |
526 | "Low Latency Frequency Transition capable processors"); | 451 | MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " |
527 | MODULE_LICENSE ("GPL"); | 452 | "Low Latency Frequency Transition capable processors"); |
453 | MODULE_LICENSE("GPL"); | ||
528 | 454 | ||
529 | module_init(cpufreq_gov_dbs_init); | 455 | module_init(cpufreq_gov_dbs_init); |
530 | module_exit(cpufreq_gov_dbs_exit); | 456 | module_exit(cpufreq_gov_dbs_exit); |