cpufreq: Add cpu utilization statistics to aid decisions made by userspace.
Understanding system load as seen by cpufreq can help userspace
algorithms make better decisions to improve system responsiveness.
One such example would be the MP decision algorithm which mines
various system info to make decisions on hotplugging in/out
the additional cores.
Change-Id: I277db7e1a7803a3822b61e7befa25131487cfe17
Signed-off-by: Anitha Anand <anithas@codeaurora.org>
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 36375c05..90311b2 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -281,8 +281,23 @@
}
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+/**
+ * cpufreq_notify_utilization - notify CPU userspace about CPU utilization
+ * change
+ *
+ * This function is called everytime the CPU load is evaluated by the
+ * ondemand governor. It notifies userspace of cpu load changes via sysfs.
+ */
+void cpufreq_notify_utilization(struct cpufreq_policy *policy,
+ unsigned int util)
+{
+ if (policy)
+ policy->util = util;
+ if (policy->util >= MIN_CPU_UTIL_NOTIFY)
+ sysfs_notify(&policy->kobj, NULL, "cpu_utilization");
+}
/*********************************************************************
* SYSFS INTERFACE *
@@ -370,6 +385,7 @@
show_one(scaling_min_freq, min);
show_one(scaling_max_freq, max);
show_one(scaling_cur_freq, cur);
+show_one(cpu_utilization, util);
static int __cpufreq_set_policy(struct cpufreq_policy *data,
struct cpufreq_policy *policy);
@@ -584,6 +600,7 @@
cpufreq_freq_attr_ro(bios_limit);
cpufreq_freq_attr_ro(related_cpus);
cpufreq_freq_attr_ro(affected_cpus);
+cpufreq_freq_attr_ro(cpu_utilization);
cpufreq_freq_attr_rw(scaling_min_freq);
cpufreq_freq_attr_rw(scaling_max_freq);
cpufreq_freq_attr_rw(scaling_governor);
@@ -596,6 +613,7 @@
&scaling_min_freq.attr,
&scaling_max_freq.attr,
&affected_cpus.attr,
+ &cpu_utilization.attr,
&related_cpus.attr,
&scaling_governor.attr,
&scaling_driver.attr,
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2d33096..cfc2534 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -552,7 +552,11 @@
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
{
+ /* Extrapolated load of this CPU */
+ unsigned int load_at_max_freq = 0;
unsigned int max_load_freq;
+ /* Current load across this CPU */
+ unsigned int cur_load = 0;
struct cpufreq_policy *policy;
unsigned int j;
@@ -579,7 +583,7 @@
struct cpu_dbs_info_s *j_dbs_info;
cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
unsigned int idle_time, wall_time, iowait_time;
- unsigned int load, load_freq;
+ unsigned int load_freq;
int freq_avg;
j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
@@ -629,16 +633,20 @@
if (unlikely(!wall_time || wall_time < idle_time))
continue;
- load = 100 * (wall_time - idle_time) / wall_time;
+ cur_load = 100 * (wall_time - idle_time) / wall_time;
freq_avg = __cpufreq_driver_getavg(policy, j);
if (freq_avg <= 0)
freq_avg = policy->cur;
- load_freq = load * freq_avg;
+ load_freq = cur_load * freq_avg;
if (load_freq > max_load_freq)
max_load_freq = load_freq;
}
+ /* calculate the scaled load across CPU */
+ load_at_max_freq = (cur_load * policy->cur)/policy->cpuinfo.max_freq;
+
+ cpufreq_notify_utilization(policy, load_at_max_freq);
/* Check for frequency increase */
if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 957c5b4..2e0e32e 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -56,6 +56,10 @@
#define CPUFREQ_POLICY_POWERSAVE (1)
#define CPUFREQ_POLICY_PERFORMANCE (2)
+/* Minimum frequency cutoff to notify the userspace about cpu utilization
+ * changes */
+#define MIN_CPU_UTIL_NOTIFY 40
+
/* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per
* cent / per mille means.
@@ -96,6 +100,7 @@
unsigned int max; /* in kHz */
unsigned int cur; /* in kHz, only needed if cpufreq
* governors are used */
+ unsigned int util; /* CPU utilization at max frequency */
unsigned int policy; /* see above */
struct cpufreq_governor *governor; /* see below */
@@ -255,7 +260,8 @@
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
-
+void cpufreq_notify_utilization(struct cpufreq_policy *policy,
+ unsigned int load);
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max)
{