cpufreq: interactive: add io_is_busy interface
Previously the idle time returned from get_cpu_idle_time_us included the
iowait time. So the iowait time was always calculated as idle time.
But now the idle time returned from get_cpu_idle_time_us does not include
the iowait time anymore because of below commit which cause the iowait time
always calculated as busy time:
6beea0c nohz: Fix update_ts_time_stat idle accounting
Add the io_is_busy interface, as does the ondemand governor, and let the user
configure the iowait time as busy or idle through the io_is_busy sysfs
interface.
By default, io_is_busy is disabled.
[toddpoynor@google.com: minor updates]
Change-Id: If7d70ff864c43bc9c8d7fd7cfc66f930d339f9b4
Signed-off-by: Lianwei Wang <lian-wei.wang@motorola.com>
Signed-off-by: Todd Poynor <toddpoynor@google.com>
This commit is contained in:
committed by
John Stultz
parent
c9d7bc6364
commit
6b2fd6c4f2
@@ -30,6 +30,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <asm/cputime.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
@@ -114,6 +115,8 @@ static u64 boostpulse_endtime;
|
||||
#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE)
|
||||
static int timer_slack_val = DEFAULT_TIMER_SLACK;
|
||||
|
||||
static bool io_is_busy;
|
||||
|
||||
static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
|
||||
unsigned int event);
|
||||
|
||||
@@ -127,6 +130,42 @@ struct cpufreq_governor cpufreq_gov_interactive = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
|
||||
cputime64_t *wall)
|
||||
{
|
||||
u64 idle_time;
|
||||
u64 cur_wall_time;
|
||||
u64 busy_time;
|
||||
|
||||
cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
|
||||
|
||||
busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
|
||||
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
|
||||
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
|
||||
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
|
||||
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
|
||||
busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
|
||||
|
||||
idle_time = cur_wall_time - busy_time;
|
||||
if (wall)
|
||||
*wall = jiffies_to_usecs(cur_wall_time);
|
||||
|
||||
return jiffies_to_usecs(idle_time);
|
||||
}
|
||||
|
||||
static inline cputime64_t get_cpu_idle_time(unsigned int cpu,
|
||||
cputime64_t *wall)
|
||||
{
|
||||
u64 idle_time = get_cpu_idle_time_us(cpu, wall);
|
||||
|
||||
if (idle_time == -1ULL)
|
||||
idle_time = get_cpu_idle_time_jiffy(cpu, wall);
|
||||
else if (!io_is_busy)
|
||||
idle_time += get_cpu_iowait_time_us(cpu, wall);
|
||||
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
static void cpufreq_interactive_timer_resched(
|
||||
struct cpufreq_interactive_cpuinfo *pcpu)
|
||||
{
|
||||
@@ -141,7 +180,7 @@ static void cpufreq_interactive_timer_resched(
|
||||
|
||||
spin_lock_irqsave(&pcpu->load_lock, flags);
|
||||
pcpu->time_in_idle =
|
||||
get_cpu_idle_time_us(smp_processor_id(),
|
||||
get_cpu_idle_time(smp_processor_id(),
|
||||
&pcpu->time_in_idle_timestamp);
|
||||
pcpu->cputime_speedadj = 0;
|
||||
pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
|
||||
@@ -278,7 +317,7 @@ static u64 update_load(int cpu)
|
||||
unsigned int delta_time;
|
||||
u64 active_time;
|
||||
|
||||
now_idle = get_cpu_idle_time_us(cpu, &now);
|
||||
now_idle = get_cpu_idle_time(cpu, &now);
|
||||
delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
|
||||
delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
|
||||
active_time = delta_time - delta_idle;
|
||||
@@ -924,6 +963,28 @@ static ssize_t store_boostpulse_duration(
|
||||
|
||||
define_one_global_rw(boostpulse_duration);
|
||||
|
||||
static ssize_t show_io_is_busy(struct kobject *kobj,
|
||||
struct attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", io_is_busy);
|
||||
}
|
||||
|
||||
static ssize_t store_io_is_busy(struct kobject *kobj,
|
||||
struct attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
unsigned long val;
|
||||
|
||||
ret = kstrtoul(buf, 0, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
io_is_busy = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct global_attr io_is_busy_attr = __ATTR(io_is_busy, 0644,
|
||||
show_io_is_busy, store_io_is_busy);
|
||||
|
||||
static struct attribute *interactive_attributes[] = {
|
||||
&target_loads_attr.attr,
|
||||
&above_hispeed_delay_attr.attr,
|
||||
@@ -935,6 +996,7 @@ static struct attribute *interactive_attributes[] = {
|
||||
&boost.attr,
|
||||
&boostpulse.attr,
|
||||
&boostpulse_duration.attr,
|
||||
&io_is_busy_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user