summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-05-27 20:53:27 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:52:17 -0800
commit2f4cbf8a0212c09bf226114eb66b5285fde70d23 (patch)
tree168373f48da8731b55fff2b2417fe21cc032f69f /drivers/cpufreq
parentc2bfeab50a61f76353cd6fbbe7d15c79082ff334 (diff)
cpufreq interactive governor: Update target frequency calculation
Updated target frequency calculation algorithm to take into account current rate CPU is running at: - When CPU is running below go_maxspeed_load threshold, adjust the target frequency based on current rate to reach tunable sustainable load (instead of applying cpu load to max possible cpu rate). Tuned by setting new node ("0" falls back to using max_rate): /sys/devices/system/cpu/cpufreq/interactive/sustain_load - When CPU is running at/above go_maxspeed_load threshold, ramp the target frequency starting from current exponentially with tunable base (instead of immediate jump to maximum cpu rate). Tuned by setting new node ("0" falls back to jump to max_rate): /sys/devices/system/cpu/cpufreq/interactive/boost_factor Defaults for the new tunning parameters are set to "0" - so no changes in governor default behavior. Original-Change-Id: Ie845d747239ba177e6f06b73965c3213649f8135 Reviewed-on: http://git-master/r/34583 Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Chih-Lung Huang <lhuang@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Narendra Damahe <ndamahe@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com> Rebase-Id: Re898a7b96d3c1b7343e773aab9788e4ff2b1d7f8
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c86
1 files changed, 76 insertions, 10 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index e1d5015f1f5e..b06f2b97cb54 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -62,6 +62,15 @@ static struct mutex set_speed_lock;
#define DEFAULT_GO_MAXSPEED_LOAD 95
static unsigned long go_maxspeed_load;
+/* Base of exponential raise to max speed; if 0 - jump to maximum */
+static unsigned long boost_factor;
+
+/*
+ * Targeted sustainable load relatively to current frequency.
+ * If 0, target is set realtively to the max speed
+ */
+static unsigned long sustain_load;
+
/*
* The minimum amount of time to spend at a frequency before we can ramp down.
*/
@@ -87,6 +96,36 @@ struct cpufreq_governor cpufreq_gov_interactive = {
.owner = THIS_MODULE,
};
+static unsigned int cpufreq_interactive_get_target(
+ int cpu_load, int load_since_change, struct cpufreq_policy *policy)
+{
+ unsigned int target_freq;
+
+ /*
+ * Choose greater of short-term load (since last idle timer
+ * started or timer function re-armed itself) or long-term load
+ * (since last frequency change).
+ */
+ if (load_since_change > cpu_load)
+ cpu_load = load_since_change;
+
+ if (cpu_load >= go_maxspeed_load) {
+ if (!boost_factor)
+ return policy->max;
+
+ target_freq = policy->cur * boost_factor;
+ }
+ else {
+ if (!sustain_load)
+ return policy->max * cpu_load / 100;
+
+ target_freq = policy->cur * cpu_load / sustain_load;
+ }
+
+ target_freq = min(target_freq, policy->max);
+ return target_freq;
+}
+
static void cpufreq_interactive_timer(unsigned long data)
{
unsigned int delta_idle;
@@ -152,17 +191,12 @@ static void cpufreq_interactive_timer(unsigned long data)
100 * (delta_time - delta_idle) / delta_time;
/*
- * Choose greater of short-term load (since last idle timer
- * started or timer function re-armed itself) or long-term load
- * (since last frequency change).
+ * Combine short-term load (since last idle timer started or timer
+ * function re-armed itself) and long-term load (since last frequency
+ * change) to determine new target frequency
*/
- if (load_since_change > cpu_load)
- cpu_load = load_since_change;
-
- if (cpu_load >= go_maxspeed_load)
- new_freq = pcpu->policy->max;
- else
- new_freq = pcpu->policy->max * cpu_load / 100;
+ new_freq = cpufreq_interactive_get_target(cpu_load, load_since_change,
+ pcpu->policy);
if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,
new_freq, CPUFREQ_RELATION_H,
@@ -445,6 +479,36 @@ static ssize_t store_go_maxspeed_load(struct kobject *kobj,
static struct global_attr go_maxspeed_load_attr = __ATTR(go_maxspeed_load, 0644,
show_go_maxspeed_load, store_go_maxspeed_load);
+static ssize_t show_boost_factor(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", boost_factor);
+}
+
+static ssize_t store_boost_factor(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t count)
+{
+ return strict_strtoul(buf, 0, &boost_factor);
+}
+
+static struct global_attr boost_factor_attr = __ATTR(boost_factor, 0644,
+ show_boost_factor, store_boost_factor);
+
+static ssize_t show_sustain_load(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%lu\n", sustain_load);
+}
+
+static ssize_t store_sustain_load(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t count)
+{
+ return strict_strtoul(buf, 0, &sustain_load);
+}
+
+static struct global_attr sustain_load_attr = __ATTR(sustain_load, 0644,
+ show_sustain_load, store_sustain_load);
+
static ssize_t show_min_sample_time(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -491,6 +555,8 @@ static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644,
static struct attribute *interactive_attributes[] = {
&go_maxspeed_load_attr.attr,
+ &boost_factor_attr.attr,
+ &sustain_load_attr.attr,
&min_sample_time_attr.attr,
&timer_rate_attr.attr,
NULL,