aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorStratos Karafotis <stratosk@semaphore.gr>2013-02-28 11:57:32 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-31 19:11:35 -0400
commit9366d84052e7c5b2eca804c08cfcd00b490f4de2 (patch)
tree0f159a425d29f1c6be12dbf30f18a55b79ae72d2 /drivers/cpufreq
parentfed573d5c91ab8f12801740cfac0567e33635b1e (diff)
cpufreq: governors: Calculate iowait time only when necessary
Currently we always calculate the CPU iowait time and add it to idle time. If we are in ondemand and we use io_is_busy, we re-calculate iowait time and we subtract it from idle time. With this patch iowait time is calculated only when necessary avoiding the double call to get_cpu_iowait_time_us. We use a parameter in function get_cpu_idle_time to distinguish when the iowait time will be added to idle time or not, without the need of keeping the prev_io_wait. Signed-off-by: Stratos Karafotis <stratosk@semaphore.gr> Acked-by: Viresh Kumar <viresh.kumar@linaro.,org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_governor.c48
-rw-r--r--drivers/cpufreq/cpufreq_governor.h3
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c11
4 files changed, 30 insertions, 34 deletions
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index a4af9c3f309e..52f76b19a883 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -240,7 +240,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
240 struct cs_cpu_dbs_info_s *dbs_info; 240 struct cs_cpu_dbs_info_s *dbs_info;
241 dbs_info = &per_cpu(cs_cpu_dbs_info, j); 241 dbs_info = &per_cpu(cs_cpu_dbs_info, j);
242 dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, 242 dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
243 &dbs_info->cdbs.prev_cpu_wall); 243 &dbs_info->cdbs.prev_cpu_wall, 0);
244 if (cs_tuners->ignore_nice) 244 if (cs_tuners->ignore_nice)
245 dbs_info->cdbs.prev_cpu_nice = 245 dbs_info->cdbs.prev_cpu_nice =
246 kcpustat_cpu(j).cpustat[CPUTIME_NICE]; 246 kcpustat_cpu(j).cpustat[CPUTIME_NICE];
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 326f0c2e2bd5..443442df113b 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -67,13 +67,13 @@ static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
67 return cputime_to_usecs(idle_time); 67 return cputime_to_usecs(idle_time);
68} 68}
69 69
70u64 get_cpu_idle_time(unsigned int cpu, u64 *wall) 70u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
71{ 71{
72 u64 idle_time = get_cpu_idle_time_us(cpu, NULL); 72 u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL);
73 73
74 if (idle_time == -1ULL) 74 if (idle_time == -1ULL)
75 return get_cpu_idle_time_jiffy(cpu, wall); 75 return get_cpu_idle_time_jiffy(cpu, wall);
76 else 76 else if (!io_busy)
77 idle_time += get_cpu_iowait_time_us(cpu, wall); 77 idle_time += get_cpu_iowait_time_us(cpu, wall);
78 78
79 return idle_time; 79 return idle_time;
@@ -100,13 +100,22 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
100 /* Get Absolute Load (in terms of freq for ondemand gov) */ 100 /* Get Absolute Load (in terms of freq for ondemand gov) */
101 for_each_cpu(j, policy->cpus) { 101 for_each_cpu(j, policy->cpus) {
102 struct cpu_dbs_common_info *j_cdbs; 102 struct cpu_dbs_common_info *j_cdbs;
103 u64 cur_wall_time, cur_idle_time, cur_iowait_time; 103 u64 cur_wall_time, cur_idle_time;
104 unsigned int idle_time, wall_time, iowait_time; 104 unsigned int idle_time, wall_time;
105 unsigned int load; 105 unsigned int load;
106 int io_busy = 0;
106 107
107 j_cdbs = dbs_data->cdata->get_cpu_cdbs(j); 108 j_cdbs = dbs_data->cdata->get_cpu_cdbs(j);
108 109
109 cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); 110 /*
111 * For the purpose of ondemand, waiting for disk IO is
112 * an indication that you're performance critical, and
113 * not that the system is actually idle. So do not add
114 * the iowait time to the cpu idle time.
115 */
116 if (dbs_data->cdata->governor == GOV_ONDEMAND)
117 io_busy = od_tuners->io_is_busy;
118 cur_idle_time = get_cpu_idle_time(j, &cur_wall_time, io_busy);
110 119
111 wall_time = (unsigned int) 120 wall_time = (unsigned int)
112 (cur_wall_time - j_cdbs->prev_cpu_wall); 121 (cur_wall_time - j_cdbs->prev_cpu_wall);
@@ -134,29 +143,6 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
134 idle_time += jiffies_to_usecs(cur_nice_jiffies); 143 idle_time += jiffies_to_usecs(cur_nice_jiffies);
135 } 144 }
136 145
137 if (dbs_data->cdata->governor == GOV_ONDEMAND) {
138 struct od_cpu_dbs_info_s *od_j_dbs_info =
139 dbs_data->cdata->get_cpu_dbs_info_s(cpu);
140
141 cur_iowait_time = get_cpu_iowait_time_us(j,
142 &cur_wall_time);
143 if (cur_iowait_time == -1ULL)
144 cur_iowait_time = 0;
145
146 iowait_time = (unsigned int) (cur_iowait_time -
147 od_j_dbs_info->prev_cpu_iowait);
148 od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
149
150 /*
151 * For the purpose of ondemand, waiting for disk IO is
152 * an indication that you're performance critical, and
153 * not that the system is actually idle. So subtract the
154 * iowait time from the cpu idle time.
155 */
156 if (od_tuners->io_is_busy && idle_time >= iowait_time)
157 idle_time -= iowait_time;
158 }
159
160 if (unlikely(!wall_time || wall_time < idle_time)) 146 if (unlikely(!wall_time || wall_time < idle_time))
161 continue; 147 continue;
162 148
@@ -254,6 +240,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
254 struct cs_dbs_tuners *cs_tuners = NULL; 240 struct cs_dbs_tuners *cs_tuners = NULL;
255 struct cpu_dbs_common_info *cpu_cdbs; 241 struct cpu_dbs_common_info *cpu_cdbs;
256 unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu; 242 unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
243 int io_busy = 0;
257 int rc; 244 int rc;
258 245
259 if (have_governor_per_policy()) 246 if (have_governor_per_policy())
@@ -353,6 +340,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
353 sampling_rate = od_tuners->sampling_rate; 340 sampling_rate = od_tuners->sampling_rate;
354 ignore_nice = od_tuners->ignore_nice; 341 ignore_nice = od_tuners->ignore_nice;
355 od_ops = dbs_data->cdata->gov_ops; 342 od_ops = dbs_data->cdata->gov_ops;
343 io_busy = od_tuners->io_is_busy;
356 } 344 }
357 345
358 switch (event) { 346 switch (event) {
@@ -369,7 +357,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
369 j_cdbs->cpu = j; 357 j_cdbs->cpu = j;
370 j_cdbs->cur_policy = policy; 358 j_cdbs->cur_policy = policy;
371 j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, 359 j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
372 &j_cdbs->prev_cpu_wall); 360 &j_cdbs->prev_cpu_wall, io_busy);
373 if (ignore_nice) 361 if (ignore_nice)
374 j_cdbs->prev_cpu_nice = 362 j_cdbs->prev_cpu_nice =
375 kcpustat_cpu(j).cpustat[CPUTIME_NICE]; 363 kcpustat_cpu(j).cpustat[CPUTIME_NICE];
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index c9c269f2b973..513cc8234e5e 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -148,7 +148,6 @@ struct cpu_dbs_common_info {
148 148
149struct od_cpu_dbs_info_s { 149struct od_cpu_dbs_info_s {
150 struct cpu_dbs_common_info cdbs; 150 struct cpu_dbs_common_info cdbs;
151 u64 prev_cpu_iowait;
152 struct cpufreq_frequency_table *freq_table; 151 struct cpufreq_frequency_table *freq_table;
153 unsigned int freq_lo; 152 unsigned int freq_lo;
154 unsigned int freq_lo_jiffies; 153 unsigned int freq_lo_jiffies;
@@ -256,7 +255,7 @@ static ssize_t show_sampling_rate_min_gov_pol \
256 return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \ 255 return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \
257} 256}
258 257
259u64 get_cpu_idle_time(unsigned int cpu, u64 *wall); 258u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
260void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); 259void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
261bool need_load_eval(struct cpu_dbs_common_info *cdbs, 260bool need_load_eval(struct cpu_dbs_common_info *cdbs,
262 unsigned int sampling_rate); 261 unsigned int sampling_rate);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 459f9ee39c74..14714787b724 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -339,11 +339,20 @@ static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
339 struct od_dbs_tuners *od_tuners = dbs_data->tuners; 339 struct od_dbs_tuners *od_tuners = dbs_data->tuners;
340 unsigned int input; 340 unsigned int input;
341 int ret; 341 int ret;
342 unsigned int j;
342 343
343 ret = sscanf(buf, "%u", &input); 344 ret = sscanf(buf, "%u", &input);
344 if (ret != 1) 345 if (ret != 1)
345 return -EINVAL; 346 return -EINVAL;
346 od_tuners->io_is_busy = !!input; 347 od_tuners->io_is_busy = !!input;
348
349 /* we need to re-evaluate prev_cpu_idle */
350 for_each_online_cpu(j) {
351 struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
352 j);
353 dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
354 &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
355 }
347 return count; 356 return count;
348} 357}
349 358
@@ -414,7 +423,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
414 struct od_cpu_dbs_info_s *dbs_info; 423 struct od_cpu_dbs_info_s *dbs_info;
415 dbs_info = &per_cpu(od_cpu_dbs_info, j); 424 dbs_info = &per_cpu(od_cpu_dbs_info, j);
416 dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, 425 dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
417 &dbs_info->cdbs.prev_cpu_wall); 426 &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
418 if (od_tuners->ignore_nice) 427 if (od_tuners->ignore_nice)
419 dbs_info->cdbs.prev_cpu_nice = 428 dbs_info->cdbs.prev_cpu_nice =
420 kcpustat_cpu(j).cpustat[CPUTIME_NICE]; 429 kcpustat_cpu(j).cpustat[CPUTIME_NICE];