diff options
author | venkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com> | 2008-08-04 14:59:12 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2008-10-09 13:52:44 -0400 |
commit | 808009131046b62ac434dbc796c0fe8accaab415 (patch) | |
tree | 64b5c755b8eb5d43f8e00554032de372f36e7b4c | |
parent | 8083e4ad970e4eb567e31037060cdd4ba346f0c0 (diff) |
[CPUFREQ][6/6] cpufreq: Add idle microaccounting in ondemand governor
Use get_cpu_idle_time_us() to get micro-accounted idle information.
This enables ondemand to get more accurate idle and busy timings
than the jiffy based calculation. As a result, we can decrease
the ondemand safety gaurd band from 80-10 to 95-3.
Results in more aggressive power savings.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 3f898606e68c..39253d6d51ef 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/kernel_stat.h> | 19 | #include <linux/kernel_stat.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/hrtimer.h> | ||
22 | #include <linux/tick.h> | ||
23 | #include <linux/ktime.h> | ||
21 | 24 | ||
22 | /* | 25 | /* |
23 | * dbs is used in this file as a shortform for demandbased switching | 26 | * dbs is used in this file as a shortform for demandbased switching |
@@ -26,6 +29,8 @@ | |||
26 | 29 | ||
27 | #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) | 30 | #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) |
28 | #define DEF_FREQUENCY_UP_THRESHOLD (80) | 31 | #define DEF_FREQUENCY_UP_THRESHOLD (80) |
32 | #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) | ||
33 | #define MICRO_FREQUENCY_UP_THRESHOLD (95) | ||
29 | #define MIN_FREQUENCY_UP_THRESHOLD (11) | 34 | #define MIN_FREQUENCY_UP_THRESHOLD (11) |
30 | #define MAX_FREQUENCY_UP_THRESHOLD (100) | 35 | #define MAX_FREQUENCY_UP_THRESHOLD (100) |
31 | 36 | ||
@@ -58,6 +63,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; | |||
58 | struct cpu_dbs_info_s { | 63 | struct cpu_dbs_info_s { |
59 | cputime64_t prev_cpu_idle; | 64 | cputime64_t prev_cpu_idle; |
60 | cputime64_t prev_cpu_wall; | 65 | cputime64_t prev_cpu_wall; |
66 | cputime64_t prev_cpu_nice; | ||
61 | struct cpufreq_policy *cur_policy; | 67 | struct cpufreq_policy *cur_policy; |
62 | struct delayed_work work; | 68 | struct delayed_work work; |
63 | struct cpufreq_frequency_table *freq_table; | 69 | struct cpufreq_frequency_table *freq_table; |
@@ -97,7 +103,8 @@ static struct dbs_tuners { | |||
97 | .powersave_bias = 0, | 103 | .powersave_bias = 0, |
98 | }; | 104 | }; |
99 | 105 | ||
100 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | 106 | static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, |
107 | cputime64_t *wall) | ||
101 | { | 108 | { |
102 | cputime64_t idle_time; | 109 | cputime64_t idle_time; |
103 | cputime64_t cur_wall_time; | 110 | cputime64_t cur_wall_time; |
@@ -123,6 +130,33 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | |||
123 | return idle_time; | 130 | return idle_time; |
124 | } | 131 | } |
125 | 132 | ||
133 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | ||
134 | { | ||
135 | u64 idle_time = get_cpu_idle_time_us(cpu, wall); | ||
136 | |||
137 | if (idle_time == -1ULL) | ||
138 | return get_cpu_idle_time_jiffy(cpu, wall); | ||
139 | |||
140 | if (dbs_tuners_ins.ignore_nice) { | ||
141 | cputime64_t cur_nice; | ||
142 | unsigned long cur_nice_jiffies; | ||
143 | struct cpu_dbs_info_s *dbs_info; | ||
144 | |||
145 | dbs_info = &per_cpu(cpu_dbs_info, cpu); | ||
146 | cur_nice = cputime64_sub(kstat_cpu(cpu).cpustat.nice, | ||
147 | dbs_info->prev_cpu_nice); | ||
148 | /* | ||
149 | * Assumption: nice time between sampling periods will be | ||
150 | * less than 2^32 jiffies for 32 bit sys | ||
151 | */ | ||
152 | cur_nice_jiffies = (unsigned long) | ||
153 | cputime64_to_jiffies64(cur_nice); | ||
154 | dbs_info->prev_cpu_nice = kstat_cpu(cpu).cpustat.nice; | ||
155 | return idle_time + jiffies_to_usecs(cur_nice_jiffies); | ||
156 | } | ||
157 | return idle_time; | ||
158 | } | ||
159 | |||
126 | /* | 160 | /* |
127 | * Find right freq to be set now with powersave_bias on. | 161 | * Find right freq to be set now with powersave_bias on. |
128 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | 162 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, |
@@ -603,6 +637,15 @@ EXPORT_SYMBOL(cpufreq_gov_ondemand); | |||
603 | static int __init cpufreq_gov_dbs_init(void) | 637 | static int __init cpufreq_gov_dbs_init(void) |
604 | { | 638 | { |
605 | int err; | 639 | int err; |
640 | cputime64_t wall; | ||
641 | u64 idle_time = get_cpu_idle_time_us(smp_processor_id(), &wall); | ||
642 | |||
643 | if (idle_time != -1ULL) { | ||
644 | /* Idle micro accounting is supported. Use finer thresholds */ | ||
645 | dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; | ||
646 | dbs_tuners_ins.down_differential = | ||
647 | MICRO_FREQUENCY_DOWN_DIFFERENTIAL; | ||
648 | } | ||
606 | 649 | ||
607 | kondemand_wq = create_workqueue("kondemand"); | 650 | kondemand_wq = create_workqueue("kondemand"); |
608 | if (!kondemand_wq) { | 651 | if (!kondemand_wq) { |