aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 20:50:22 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 20:50:22 -0400
commit2ee8099f2c2bc74a7c2fac7f83e12a5d651681d3 (patch)
tree433ebb87a3d5d02e7df3700c846ac9af632c55f3 /drivers
parentc03efdb202a4882f426ce49766859af4058c9b8a (diff)
parent24669f7d00d387799fc6a39452ab22d7f078f043 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq: [CPUFREQ] sw_any_bug_dmi_table can be used on resume, so it isn't initdata [CPUFREQ] Fix some more CPU hotplug locking. [CPUFREQ] Workaround for BIOS bug in software coordination of frequency [CPUFREQ] Longhaul - Add voltage scaling to driver [CPUFREQ] Fix sparse warning in ondemand [CPUFREQ] make drivers/cpufreq/cpufreq_ondemand.c:powersave_bias_target() static [CPUFREQ] Longhaul - Add ignore_latency option [CPUFREQ] Longhaul - Disable arbiter [CPUFREQ][2/2] ondemand: updated add powersave_bias tunable [CPUFREQ][1/2] ondemand: updated tune for hardware coordination [CPUFREQ] Fix typo.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c173
-rw-r--r--drivers/cpufreq/cpufreq_stats.c2
3 files changed, 151 insertions, 26 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b3df613ae4ec..d35a9f06ab7b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -32,7 +32,7 @@
32#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) 32#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
33 33
34/** 34/**
35 * The "cpufreq driver" - the arch- or hardware-dependend low 35 * The "cpufreq driver" - the arch- or hardware-dependent low
36 * level driver of CPUFreq support, and its spinlock. This lock 36 * level driver of CPUFreq support, and its spinlock. This lock
37 * also protects the cpufreq_cpu_data array. 37 * also protects the cpufreq_cpu_data array.
38 */ 38 */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 52cf1f021825..bf8aa45d4f01 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -55,6 +55,10 @@ struct cpu_dbs_info_s {
55 struct cpufreq_policy *cur_policy; 55 struct cpufreq_policy *cur_policy;
56 struct work_struct work; 56 struct work_struct work;
57 unsigned int enable; 57 unsigned int enable;
58 struct cpufreq_frequency_table *freq_table;
59 unsigned int freq_lo;
60 unsigned int freq_lo_jiffies;
61 unsigned int freq_hi_jiffies;
58}; 62};
59static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); 63static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
60 64
@@ -72,15 +76,15 @@ static DEFINE_MUTEX(dbs_mutex);
72 76
73static struct workqueue_struct *kondemand_wq; 77static struct workqueue_struct *kondemand_wq;
74 78
75struct dbs_tuners { 79static struct dbs_tuners {
76 unsigned int sampling_rate; 80 unsigned int sampling_rate;
77 unsigned int up_threshold; 81 unsigned int up_threshold;
78 unsigned int ignore_nice; 82 unsigned int ignore_nice;
79}; 83 unsigned int powersave_bias;
80 84} dbs_tuners_ins = {
81static struct dbs_tuners dbs_tuners_ins = {
82 .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, 85 .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
83 .ignore_nice = 0, 86 .ignore_nice = 0,
87 .powersave_bias = 0,
84}; 88};
85 89
86static inline cputime64_t get_cpu_idle_time(unsigned int cpu) 90static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
@@ -96,6 +100,70 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
96 return retval; 100 return retval;
97} 101}
98 102
103/*
104 * Find right freq to be set now with powersave_bias on.
105 * Returns the freq_hi to be used right now and will set freq_hi_jiffies,
106 * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
107 */
108static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
109 unsigned int freq_next,
110 unsigned int relation)
111{
112 unsigned int freq_req, freq_reduc, freq_avg;
113 unsigned int freq_hi, freq_lo;
114 unsigned int index = 0;
115 unsigned int jiffies_total, jiffies_hi, jiffies_lo;
116 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, policy->cpu);
117
118 if (!dbs_info->freq_table) {
119 dbs_info->freq_lo = 0;
120 dbs_info->freq_lo_jiffies = 0;
121 return freq_next;
122 }
123
124 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
125 relation, &index);
126 freq_req = dbs_info->freq_table[index].frequency;
127 freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000;
128 freq_avg = freq_req - freq_reduc;
129
130 /* Find freq bounds for freq_avg in freq_table */
131 index = 0;
132 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg,
133 CPUFREQ_RELATION_H, &index);
134 freq_lo = dbs_info->freq_table[index].frequency;
135 index = 0;
136 cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg,
137 CPUFREQ_RELATION_L, &index);
138 freq_hi = dbs_info->freq_table[index].frequency;
139
140 /* Find out how long we have to be in hi and lo freqs */
141 if (freq_hi == freq_lo) {
142 dbs_info->freq_lo = 0;
143 dbs_info->freq_lo_jiffies = 0;
144 return freq_lo;
145 }
146 jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
147 jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
148 jiffies_hi += ((freq_hi - freq_lo) / 2);
149 jiffies_hi /= (freq_hi - freq_lo);
150 jiffies_lo = jiffies_total - jiffies_hi;
151 dbs_info->freq_lo = freq_lo;
152 dbs_info->freq_lo_jiffies = jiffies_lo;
153 dbs_info->freq_hi_jiffies = jiffies_hi;
154 return freq_hi;
155}
156
157static void ondemand_powersave_bias_init(void)
158{
159 int i;
160 for_each_online_cpu(i) {
161 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i);
162 dbs_info->freq_table = cpufreq_frequency_get_table(i);
163 dbs_info->freq_lo = 0;
164 }
165}
166
99/************************** sysfs interface ************************/ 167/************************** sysfs interface ************************/
100static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) 168static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
101{ 169{
@@ -124,6 +192,7 @@ static ssize_t show_##file_name \
124show_one(sampling_rate, sampling_rate); 192show_one(sampling_rate, sampling_rate);
125show_one(up_threshold, up_threshold); 193show_one(up_threshold, up_threshold);
126show_one(ignore_nice_load, ignore_nice); 194show_one(ignore_nice_load, ignore_nice);
195show_one(powersave_bias, powersave_bias);
127 196
128static ssize_t store_sampling_rate(struct cpufreq_policy *unused, 197static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
129 const char *buf, size_t count) 198 const char *buf, size_t count)
@@ -198,6 +267,27 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
198 return count; 267 return count;
199} 268}
200 269
270static ssize_t store_powersave_bias(struct cpufreq_policy *unused,
271 const char *buf, size_t count)
272{
273 unsigned int input;
274 int ret;
275 ret = sscanf(buf, "%u", &input);
276
277 if (ret != 1)
278 return -EINVAL;
279
280 if (input > 1000)
281 input = 1000;
282
283 mutex_lock(&dbs_mutex);
284 dbs_tuners_ins.powersave_bias = input;
285 ondemand_powersave_bias_init();
286 mutex_unlock(&dbs_mutex);
287
288 return count;
289}
290
201#define define_one_rw(_name) \ 291#define define_one_rw(_name) \
202static struct freq_attr _name = \ 292static struct freq_attr _name = \
203__ATTR(_name, 0644, show_##_name, store_##_name) 293__ATTR(_name, 0644, show_##_name, store_##_name)
@@ -205,6 +295,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
205define_one_rw(sampling_rate); 295define_one_rw(sampling_rate);
206define_one_rw(up_threshold); 296define_one_rw(up_threshold);
207define_one_rw(ignore_nice_load); 297define_one_rw(ignore_nice_load);
298define_one_rw(powersave_bias);
208 299
209static struct attribute * dbs_attributes[] = { 300static struct attribute * dbs_attributes[] = {
210 &sampling_rate_max.attr, 301 &sampling_rate_max.attr,
@@ -212,6 +303,7 @@ static struct attribute * dbs_attributes[] = {
212 &sampling_rate.attr, 303 &sampling_rate.attr,
213 &up_threshold.attr, 304 &up_threshold.attr,
214 &ignore_nice_load.attr, 305 &ignore_nice_load.attr,
306 &powersave_bias.attr,
215 NULL 307 NULL
216}; 308};
217 309
@@ -234,6 +326,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
234 if (!this_dbs_info->enable) 326 if (!this_dbs_info->enable)
235 return; 327 return;
236 328
329 this_dbs_info->freq_lo = 0;
237 policy = this_dbs_info->cur_policy; 330 policy = this_dbs_info->cur_policy;
238 cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); 331 cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
239 total_ticks = (unsigned int) cputime64_sub(cur_jiffies, 332 total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
@@ -274,11 +367,18 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
274 /* Check for frequency increase */ 367 /* Check for frequency increase */
275 if (load > dbs_tuners_ins.up_threshold) { 368 if (load > dbs_tuners_ins.up_threshold) {
276 /* if we are already at full speed then break out early */ 369 /* if we are already at full speed then break out early */
277 if (policy->cur == policy->max) 370 if (!dbs_tuners_ins.powersave_bias) {
278 return; 371 if (policy->cur == policy->max)
279 372 return;
280 __cpufreq_driver_target(policy, policy->max, 373
281 CPUFREQ_RELATION_H); 374 __cpufreq_driver_target(policy, policy->max,
375 CPUFREQ_RELATION_H);
376 } else {
377 int freq = powersave_bias_target(policy, policy->max,
378 CPUFREQ_RELATION_H);
379 __cpufreq_driver_target(policy, freq,
380 CPUFREQ_RELATION_L);
381 }
282 return; 382 return;
283 } 383 }
284 384
@@ -293,37 +393,64 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
293 * policy. To be safe, we focus 10 points under the threshold. 393 * policy. To be safe, we focus 10 points under the threshold.
294 */ 394 */
295 if (load < (dbs_tuners_ins.up_threshold - 10)) { 395 if (load < (dbs_tuners_ins.up_threshold - 10)) {
296 unsigned int freq_next; 396 unsigned int freq_next = (policy->cur * load) /
297 freq_next = (policy->cur * load) /
298 (dbs_tuners_ins.up_threshold - 10); 397 (dbs_tuners_ins.up_threshold - 10);
299 398 if (!dbs_tuners_ins.powersave_bias) {
300 __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); 399 __cpufreq_driver_target(policy, freq_next,
400 CPUFREQ_RELATION_L);
401 } else {
402 int freq = powersave_bias_target(policy, freq_next,
403 CPUFREQ_RELATION_L);
404 __cpufreq_driver_target(policy, freq,
405 CPUFREQ_RELATION_L);
406 }
301 } 407 }
302} 408}
303 409
410/* Sampling types */
411enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
412
304static void do_dbs_timer(void *data) 413static void do_dbs_timer(void *data)
305{ 414{
306 unsigned int cpu = smp_processor_id(); 415 unsigned int cpu = smp_processor_id();
307 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); 416 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
417 /* We want all CPUs to do sampling nearly on same jiffy */
418 int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
419 delay -= jiffies % delay;
308 420
309 if (!dbs_info->enable) 421 if (!dbs_info->enable)
310 return; 422 return;
311 423 /* Common NORMAL_SAMPLE setup */
312 lock_cpu_hotplug(); 424 INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE);
313 dbs_check_cpu(dbs_info); 425 if (!dbs_tuners_ins.powersave_bias ||
314 unlock_cpu_hotplug(); 426 (unsigned long) data == DBS_NORMAL_SAMPLE) {
315 queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, 427 lock_cpu_hotplug();
316 usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); 428 dbs_check_cpu(dbs_info);
429 unlock_cpu_hotplug();
430 if (dbs_info->freq_lo) {
431 /* Setup timer for SUB_SAMPLE */
432 INIT_WORK(&dbs_info->work, do_dbs_timer,
433 (void *)DBS_SUB_SAMPLE);
434 delay = dbs_info->freq_hi_jiffies;
435 }
436 } else {
437 __cpufreq_driver_target(dbs_info->cur_policy,
438 dbs_info->freq_lo,
439 CPUFREQ_RELATION_H);
440 }
441 queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
317} 442}
318 443
319static inline void dbs_timer_init(unsigned int cpu) 444static inline void dbs_timer_init(unsigned int cpu)
320{ 445{
321 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); 446 struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
447 /* We want all CPUs to do sampling nearly on same jiffy */
448 int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
449 delay -= jiffies % delay;
322 450
323 INIT_WORK(&dbs_info->work, do_dbs_timer, 0); 451 ondemand_powersave_bias_init();
324 queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, 452 INIT_WORK(&dbs_info->work, do_dbs_timer, NULL);
325 usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); 453 queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
326 return;
327} 454}
328 455
329static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) 456static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 25eee5394201..c2ecc599dc5f 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -350,12 +350,10 @@ __init cpufreq_stats_init(void)
350 } 350 }
351 351
352 register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); 352 register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
353 lock_cpu_hotplug();
354 for_each_online_cpu(cpu) { 353 for_each_online_cpu(cpu) {
355 cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, 354 cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
356 (void *)(long)cpu); 355 (void *)(long)cpu);
357 } 356 }
358 unlock_cpu_hotplug();
359 return 0; 357 return 0;
360} 358}
361static void 359static void