diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 75 | ||||
-rw-r--r-- | drivers/xen/manage.c | 14 |
2 files changed, 75 insertions, 14 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc93cf2..8e9dbdc6c700 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -73,6 +73,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; | |||
73 | 73 | ||
74 | struct cpu_dbs_info_s { | 74 | struct cpu_dbs_info_s { |
75 | cputime64_t prev_cpu_idle; | 75 | cputime64_t prev_cpu_idle; |
76 | cputime64_t prev_cpu_iowait; | ||
76 | cputime64_t prev_cpu_wall; | 77 | cputime64_t prev_cpu_wall; |
77 | cputime64_t prev_cpu_nice; | 78 | cputime64_t prev_cpu_nice; |
78 | struct cpufreq_policy *cur_policy; | 79 | struct cpufreq_policy *cur_policy; |
@@ -108,6 +109,7 @@ static struct dbs_tuners { | |||
108 | unsigned int down_differential; | 109 | unsigned int down_differential; |
109 | unsigned int ignore_nice; | 110 | unsigned int ignore_nice; |
110 | unsigned int powersave_bias; | 111 | unsigned int powersave_bias; |
112 | unsigned int io_is_busy; | ||
111 | } dbs_tuners_ins = { | 113 | } dbs_tuners_ins = { |
112 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 114 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
113 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, | 115 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, |
@@ -148,6 +150,16 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | |||
148 | return idle_time; | 150 | return idle_time; |
149 | } | 151 | } |
150 | 152 | ||
153 | static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) | ||
154 | { | ||
155 | u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); | ||
156 | |||
157 | if (iowait_time == -1ULL) | ||
158 | return 0; | ||
159 | |||
160 | return iowait_time; | ||
161 | } | ||
162 | |||
151 | /* | 163 | /* |
152 | * Find right freq to be set now with powersave_bias on. | 164 | * Find right freq to be set now with powersave_bias on. |
153 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | 165 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, |
@@ -249,6 +261,7 @@ static ssize_t show_##file_name \ | |||
249 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | 261 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ |
250 | } | 262 | } |
251 | show_one(sampling_rate, sampling_rate); | 263 | show_one(sampling_rate, sampling_rate); |
264 | show_one(io_is_busy, io_is_busy); | ||
252 | show_one(up_threshold, up_threshold); | 265 | show_one(up_threshold, up_threshold); |
253 | show_one(ignore_nice_load, ignore_nice); | 266 | show_one(ignore_nice_load, ignore_nice); |
254 | show_one(powersave_bias, powersave_bias); | 267 | show_one(powersave_bias, powersave_bias); |
@@ -299,6 +312,23 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, | |||
299 | return count; | 312 | return count; |
300 | } | 313 | } |
301 | 314 | ||
315 | static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, | ||
316 | const char *buf, size_t count) | ||
317 | { | ||
318 | unsigned int input; | ||
319 | int ret; | ||
320 | |||
321 | ret = sscanf(buf, "%u", &input); | ||
322 | if (ret != 1) | ||
323 | return -EINVAL; | ||
324 | |||
325 | mutex_lock(&dbs_mutex); | ||
326 | dbs_tuners_ins.io_is_busy = !!input; | ||
327 | mutex_unlock(&dbs_mutex); | ||
328 | |||
329 | return count; | ||
330 | } | ||
331 | |||
302 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, | 332 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, |
303 | const char *buf, size_t count) | 333 | const char *buf, size_t count) |
304 | { | 334 | { |
@@ -381,6 +411,7 @@ static struct global_attr _name = \ | |||
381 | __ATTR(_name, 0644, show_##_name, store_##_name) | 411 | __ATTR(_name, 0644, show_##_name, store_##_name) |
382 | 412 | ||
383 | define_one_rw(sampling_rate); | 413 | define_one_rw(sampling_rate); |
414 | define_one_rw(io_is_busy); | ||
384 | define_one_rw(up_threshold); | 415 | define_one_rw(up_threshold); |
385 | define_one_rw(ignore_nice_load); | 416 | define_one_rw(ignore_nice_load); |
386 | define_one_rw(powersave_bias); | 417 | define_one_rw(powersave_bias); |
@@ -392,6 +423,7 @@ static struct attribute *dbs_attributes[] = { | |||
392 | &up_threshold.attr, | 423 | &up_threshold.attr, |
393 | &ignore_nice_load.attr, | 424 | &ignore_nice_load.attr, |
394 | &powersave_bias.attr, | 425 | &powersave_bias.attr, |
426 | &io_is_busy.attr, | ||
395 | NULL | 427 | NULL |
396 | }; | 428 | }; |
397 | 429 | ||
@@ -470,14 +502,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
470 | 502 | ||
471 | for_each_cpu(j, policy->cpus) { | 503 | for_each_cpu(j, policy->cpus) { |
472 | struct cpu_dbs_info_s *j_dbs_info; | 504 | struct cpu_dbs_info_s *j_dbs_info; |
473 | cputime64_t cur_wall_time, cur_idle_time; | 505 | cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; |
474 | unsigned int idle_time, wall_time; | 506 | unsigned int idle_time, wall_time, iowait_time; |
475 | unsigned int load, load_freq; | 507 | unsigned int load, load_freq; |
476 | int freq_avg; | 508 | int freq_avg; |
477 | 509 | ||
478 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); | 510 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); |
479 | 511 | ||
480 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); | 512 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); |
513 | cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); | ||
481 | 514 | ||
482 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, | 515 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, |
483 | j_dbs_info->prev_cpu_wall); | 516 | j_dbs_info->prev_cpu_wall); |
@@ -487,6 +520,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
487 | j_dbs_info->prev_cpu_idle); | 520 | j_dbs_info->prev_cpu_idle); |
488 | j_dbs_info->prev_cpu_idle = cur_idle_time; | 521 | j_dbs_info->prev_cpu_idle = cur_idle_time; |
489 | 522 | ||
523 | iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, | ||
524 | j_dbs_info->prev_cpu_iowait); | ||
525 | j_dbs_info->prev_cpu_iowait = cur_iowait_time; | ||
526 | |||
490 | if (dbs_tuners_ins.ignore_nice) { | 527 | if (dbs_tuners_ins.ignore_nice) { |
491 | cputime64_t cur_nice; | 528 | cputime64_t cur_nice; |
492 | unsigned long cur_nice_jiffies; | 529 | unsigned long cur_nice_jiffies; |
@@ -504,6 +541,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
504 | idle_time += jiffies_to_usecs(cur_nice_jiffies); | 541 | idle_time += jiffies_to_usecs(cur_nice_jiffies); |
505 | } | 542 | } |
506 | 543 | ||
544 | /* | ||
545 | * For the purpose of ondemand, waiting for disk IO is an | ||
546 | * indication that you're performance critical, and not that | ||
547 | * the system is actually idle. So subtract the iowait time | ||
548 | * from the cpu idle time. | ||
549 | */ | ||
550 | |||
551 | if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) | ||
552 | idle_time -= iowait_time; | ||
553 | |||
507 | if (unlikely(!wall_time || wall_time < idle_time)) | 554 | if (unlikely(!wall_time || wall_time < idle_time)) |
508 | continue; | 555 | continue; |
509 | 556 | ||
@@ -617,6 +664,29 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | |||
617 | cancel_delayed_work_sync(&dbs_info->work); | 664 | cancel_delayed_work_sync(&dbs_info->work); |
618 | } | 665 | } |
619 | 666 | ||
667 | /* | ||
668 | * Not all CPUs want IO time to be accounted as busy; this dependson how | ||
669 | * efficient idling at a higher frequency/voltage is. | ||
670 | * Pavel Machek says this is not so for various generations of AMD and old | ||
671 | * Intel systems. | ||
672 | * Mike Chan (androidlcom) calis this is also not true for ARM. | ||
673 | * Because of this, whitelist specific known (series) of CPUs by default, and | ||
674 | * leave all others up to the user. | ||
675 | */ | ||
676 | static int should_io_be_busy(void) | ||
677 | { | ||
678 | #if defined(CONFIG_X86) | ||
679 | /* | ||
680 | * For Intel, Core 2 (model 15) andl later have an efficient idle. | ||
681 | */ | ||
682 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
683 | boot_cpu_data.x86 == 6 && | ||
684 | boot_cpu_data.x86_model >= 15) | ||
685 | return 1; | ||
686 | #endif | ||
687 | return 0; | ||
688 | } | ||
689 | |||
620 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | 690 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, |
621 | unsigned int event) | 691 | unsigned int event) |
622 | { | 692 | { |
@@ -679,6 +749,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
679 | dbs_tuners_ins.sampling_rate = | 749 | dbs_tuners_ins.sampling_rate = |
680 | max(min_sampling_rate, | 750 | max(min_sampling_rate, |
681 | latency * LATENCY_MULTIPLIER); | 751 | latency * LATENCY_MULTIPLIER); |
752 | dbs_tuners_ins.io_is_busy = should_io_be_busy(); | ||
682 | } | 753 | } |
683 | mutex_unlock(&dbs_mutex); | 754 | mutex_unlock(&dbs_mutex); |
684 | 755 | ||
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2ac4440e7b08..8943b8ccee1a 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -80,12 +80,6 @@ static void do_suspend(void) | |||
80 | 80 | ||
81 | shutting_down = SHUTDOWN_SUSPEND; | 81 | shutting_down = SHUTDOWN_SUSPEND; |
82 | 82 | ||
83 | err = stop_machine_create(); | ||
84 | if (err) { | ||
85 | printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | #ifdef CONFIG_PREEMPT | 83 | #ifdef CONFIG_PREEMPT |
90 | /* If the kernel is preemptible, we need to freeze all the processes | 84 | /* If the kernel is preemptible, we need to freeze all the processes |
91 | to prevent them from being in the middle of a pagetable update | 85 | to prevent them from being in the middle of a pagetable update |
@@ -93,7 +87,7 @@ static void do_suspend(void) | |||
93 | err = freeze_processes(); | 87 | err = freeze_processes(); |
94 | if (err) { | 88 | if (err) { |
95 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 89 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); |
96 | goto out_destroy_sm; | 90 | goto out; |
97 | } | 91 | } |
98 | #endif | 92 | #endif |
99 | 93 | ||
@@ -136,12 +130,8 @@ out_resume: | |||
136 | out_thaw: | 130 | out_thaw: |
137 | #ifdef CONFIG_PREEMPT | 131 | #ifdef CONFIG_PREEMPT |
138 | thaw_processes(); | 132 | thaw_processes(); |
139 | |||
140 | out_destroy_sm: | ||
141 | #endif | ||
142 | stop_machine_destroy(); | ||
143 | |||
144 | out: | 133 | out: |
134 | #endif | ||
145 | shutting_down = SHUTDOWN_INVALID; | 135 | shutting_down = SHUTDOWN_INVALID; |
146 | } | 136 | } |
147 | #endif /* CONFIG_PM_SLEEP */ | 137 | #endif /* CONFIG_PM_SLEEP */ |