summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
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,