aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvenkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com>2008-08-04 14:59:12 -0400
committerDave Jones <davej@redhat.com>2008-10-09 13:52:44 -0400
commit808009131046b62ac434dbc796c0fe8accaab415 (patch)
tree64b5c755b8eb5d43f8e00554032de372f36e7b4c
parent8083e4ad970e4eb567e31037060cdd4ba346f0c0 (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.c45
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};
58struct cpu_dbs_info_s { 63struct 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
100static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) 106static 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
133static 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);
603static int __init cpufreq_gov_dbs_init(void) 637static 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) {