cpufreq: interactive: add boost pulse interface

Change-Id: Icf1e86d2065cc8f0816ba9c6b065eb056d4e8249
Signed-off-by: Todd Poynor <toddpoynor@google.com>
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 97a08d9..6aed1ce 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -241,8 +241,13 @@
 input_boost: If non-zero, boost speed of all CPUs to hispeed_freq on
 touchscreen activity.  Default is 0.
 
-boost: If non-zero, immediately boost speed of all CPUs to
-hispeed_freq.  If zero, allow CPU speeds to drop below hispeed_freq.
+boost: If non-zero, immediately boost speed of all CPUs to at least
+hispeed_freq until zero is written to this attribute.  If zero, allow
+CPU speeds to drop below hispeed_freq according to load as usual.
+
+boostpulse: Immediately boost speed of all CPUs to hispeed_freq for
+min_sample_time, after which speeds are allowed to drop below
+hispeed_freq according to load as usual.
 
 
 3. The Governor Interface in the CPUfreq Core
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index e1310c4..62c6da1 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -494,7 +494,6 @@
 	unsigned long flags;
 	struct cpufreq_interactive_cpuinfo *pcpu;
 
-	trace_cpufreq_interactive_boost(hispeed_freq);
 	spin_lock_irqsave(&up_cpumask_lock, flags);
 
 	for_each_online_cpu(i) {
@@ -533,8 +532,10 @@
 					    unsigned int type,
 					    unsigned int code, int value)
 {
-	if (input_boost_val && type == EV_SYN && code == SYN_REPORT)
+	if (input_boost_val && type == EV_SYN && code == SYN_REPORT) {
+		trace_cpufreq_interactive_boost("input");
 		cpufreq_interactive_boost();
+	}
 }
 
 static void cpufreq_interactive_input_open(struct work_struct *w)
@@ -762,16 +763,36 @@
 
 	boost_val = val;
 
-	if (boost_val)
+	if (boost_val) {
+		trace_cpufreq_interactive_boost("on");
 		cpufreq_interactive_boost();
-	else
-		trace_cpufreq_interactive_unboost(hispeed_freq);
+	} else {
+		trace_cpufreq_interactive_unboost("off");
+	}
 
 	return count;
 }
 
 define_one_global_rw(boost);
 
+static ssize_t store_boostpulse(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;
+
+	trace_cpufreq_interactive_boost("pulse");
+	cpufreq_interactive_boost();
+	return count;
+}
+
+static struct global_attr boostpulse =
+	__ATTR(boostpulse, 0200, NULL, store_boostpulse);
+
 static struct attribute *interactive_attributes[] = {
 	&hispeed_freq_attr.attr,
 	&go_hispeed_load_attr.attr,
@@ -780,6 +801,7 @@
 	&timer_rate_attr.attr,
 	&input_boost.attr,
 	&boost.attr,
+	&boostpulse.attr,
 	NULL,
 };
 
diff --git a/include/trace/events/cpufreq_interactive.h b/include/trace/events/cpufreq_interactive.h
index ae6f232..0791f27 100644
--- a/include/trace/events/cpufreq_interactive.h
+++ b/include/trace/events/cpufreq_interactive.h
@@ -83,27 +83,27 @@
 );
 
 TRACE_EVENT(cpufreq_interactive_boost,
-	    TP_PROTO(unsigned long freq),
-	    TP_ARGS(freq),
+	    TP_PROTO(char *s),
+	    TP_ARGS(s),
 	    TP_STRUCT__entry(
-		    __field(unsigned long, freq)
+		    __field(char *, s)
 	    ),
 	    TP_fast_assign(
-		    __entry->freq = freq;
+		    __entry->s = s;
 	    ),
-	    TP_printk("freq=%lu", __entry->freq)
+	    TP_printk("%s", __entry->s)
 );
 
 TRACE_EVENT(cpufreq_interactive_unboost,
-	    TP_PROTO(unsigned long freq),
-	    TP_ARGS(freq),
+	    TP_PROTO(char *s),
+	    TP_ARGS(s),
 	    TP_STRUCT__entry(
-		    __field(unsigned long, freq)
+		    __field(char *, s)
 	    ),
 	    TP_fast_assign(
-		    __entry->freq = freq;
+		    __entry->s = s;
 	    ),
-	    TP_printk("freq=%lu", __entry->freq)
+	    TP_printk("%s", __entry->s)
 );
 
 #endif /* _TRACE_CPUFREQ_INTERACTIVE_H */