diff options
author | Stratos Karafotis <stratosk@semaphore.gr> | 2013-02-28 11:57:32 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-03-31 19:11:35 -0400 |
commit | 9366d84052e7c5b2eca804c08cfcd00b490f4de2 (patch) | |
tree | 0f159a425d29f1c6be12dbf30f18a55b79ae72d2 /drivers | |
parent | fed573d5c91ab8f12801740cfac0567e33635b1e (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')
-rw-r--r-- | drivers/cpufreq/cpufreq_conservative.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 48 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.h | 3 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 11 |
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 | ||
70 | u64 get_cpu_idle_time(unsigned int cpu, u64 *wall) | 70 | u64 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 | ||
149 | struct od_cpu_dbs_info_s { | 149 | struct 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 | ||
259 | u64 get_cpu_idle_time(unsigned int cpu, u64 *wall); | 258 | u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); |
260 | void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); | 259 | void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); |
261 | bool need_load_eval(struct cpu_dbs_common_info *cdbs, | 260 | bool 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]; |