diff options
author | Jinyoung Park <jinyoungp@nvidia.com> | 2014-03-20 20:51:42 +0900 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2014-04-30 13:12:21 -0700 |
commit | f0720f10c5109a744f0a4809851557d2c4377c02 (patch) | |
tree | 645d6df586aed69f206bbebec03fa582b644d5e4 /drivers/cpufreq | |
parent | 2c936d6cb3e940a8dfe857fac445d0d5d717c8b9 (diff) |
cpufreq: interactive: Add consecutive I/O
Considered I/O wait as CPU busy if I/O wait is observed on consecutive samples.
Bug 1371832
Bug 1447792
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/401407
(cherry picked from commit 04f29c065b5ecfdbed9535a1b1709dee1fd8806f)
Change-Id: Iac3344c1a933663aea0f6ffe841690af31d286e1
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/402788
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/cpufreq_interactive.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index e6bef7c8a18f..9c62003a19a8 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -42,8 +42,10 @@ struct cpufreq_interactive_cpuinfo { spinlock_t load_lock; /* protects the next 4 fields */ u64 time_in_idle; u64 time_in_idle_timestamp; + u64 time_in_iowait; u64 cputime_speedadj; u64 cputime_speedadj_timestamp; + unsigned int io_consecutive; struct cpufreq_policy *policy; struct cpufreq_frequency_table *freq_table; unsigned int target_freq; @@ -123,6 +125,9 @@ struct cpufreq_interactive_tunables { bool io_is_busy; + /* Consider IO as busy if consecutive IOs are above this value. */ + unsigned long io_busy_threshold; + /* Base of exponential raise to max speed; if 0 - jump to * hispeed_freq */ @@ -150,6 +155,7 @@ static void cpufreq_interactive_timer_resched( get_cpu_idle_time(smp_processor_id(), &pcpu->time_in_idle_timestamp, tunables->io_is_busy); + pcpu->time_in_iowait = get_cpu_iowait_time_us(smp_processor_id(), NULL); pcpu->cputime_speedadj = 0; pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; expires = jiffies + usecs_to_jiffies(tunables->timer_rate); @@ -189,6 +195,8 @@ static void cpufreq_interactive_timer_start( pcpu->time_in_idle = get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp, tunables->io_is_busy); + pcpu->time_in_iowait = get_cpu_iowait_time_us(cpu, NULL); + pcpu->io_consecutive = 0; pcpu->cputime_speedadj = 0; pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; spin_unlock_irqrestore(&pcpu->load_lock, flags); @@ -328,13 +336,32 @@ static u64 update_load(int cpu) pcpu->policy->governor_data; u64 now; u64 now_idle; + u64 now_iowait; unsigned int delta_idle; + unsigned int delta_iowait; unsigned int delta_time; + unsigned int io_consecutive; u64 active_time; now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy); + now_iowait = get_cpu_iowait_time_us(cpu, NULL); delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle); + delta_iowait = (unsigned int)(now_iowait - pcpu->time_in_iowait); delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp); + io_consecutive = pcpu->io_consecutive; + + if (!tunables->io_is_busy) { + if (tunables->io_busy_threshold && delta_iowait) + io_consecutive = + (io_consecutive < tunables->io_busy_threshold) ? + io_consecutive + 1 : io_consecutive; + else if (io_consecutive) + io_consecutive--; + + if (io_consecutive && + (io_consecutive >= tunables->io_busy_threshold)) + delta_idle -= delta_iowait; + } if (delta_time <= delta_idle) active_time = 0; @@ -344,7 +371,9 @@ static u64 update_load(int cpu) pcpu->cputime_speedadj += active_time * pcpu->policy->cur; pcpu->time_in_idle = now_idle; + pcpu->time_in_iowait = now_iowait; pcpu->time_in_idle_timestamp = now; + pcpu->io_consecutive = io_consecutive; return now; } @@ -998,6 +1027,26 @@ static ssize_t store_io_is_busy(struct cpufreq_interactive_tunables *tunables, return count; } +static ssize_t show_io_busy_threshold( + struct cpufreq_interactive_tunables *tunables, char *buf) +{ + return sprintf(buf, "%lu\n", tunables->io_busy_threshold); +} + +static ssize_t store_io_busy_threshold( + struct cpufreq_interactive_tunables *tunables, const char *buf, + size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + tunables->io_busy_threshold = val; + return count; +} + /* * Create show/store routines * - sys: One governor instance for complete SYSTEM @@ -1046,6 +1095,7 @@ show_store_gov_pol_sys(boost); store_gov_pol_sys(boostpulse); show_store_gov_pol_sys(boostpulse_duration); show_store_gov_pol_sys(io_is_busy); +show_store_gov_pol_sys(io_busy_threshold); gov_sys_pol_attr_rw(target_loads); gov_sys_pol_attr_rw(above_hispeed_delay); @@ -1058,6 +1108,7 @@ gov_sys_pol_attr_rw(timer_slack); gov_sys_pol_attr_rw(boost); gov_sys_pol_attr_rw(boostpulse_duration); gov_sys_pol_attr_rw(io_is_busy); +gov_sys_pol_attr_rw(io_busy_threshold); static struct global_attr boostpulse_gov_sys = __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_sys); @@ -1078,6 +1129,7 @@ static struct attribute *interactive_attributes_gov_sys[] = { &boostpulse_gov_sys.attr, &boostpulse_duration_gov_sys.attr, &io_is_busy_gov_sys.attr, + &io_busy_threshold_gov_sys.attr, &boost_factor_gov_sys.attr, NULL, }; @@ -1100,6 +1152,7 @@ static struct attribute *interactive_attributes_gov_pol[] = { &boostpulse_gov_pol.attr, &boostpulse_duration_gov_pol.attr, &io_is_busy_gov_pol.attr, + &io_busy_threshold_gov_pol.attr, &boost_factor_gov_pol.attr, NULL, }; |