diff options
| -rw-r--r-- | drivers/cpufreq/cpufreq_interactive.c | 52 | 
1 files changed, 45 insertions, 7 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index d0d51ee3072..8b44a82aa14 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -95,11 +95,12 @@ static unsigned long timer_rate;  #define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE  static unsigned long above_hispeed_delay_val; -/* - * Non-zero means longer-term speed boost active. - */ - +/* Non-zero means indefinite speed boost active */  static int boost_val; +/* Duration of a boot pulse in usecs */ +static int boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; +/* End time of boost pulse in ktime converted to usecs */ +static u64 boostpulse_endtime;  static bool governidle;  module_param(governidle, bool, S_IWUSR | S_IRUGO); @@ -268,6 +269,7 @@ static void cpufreq_interactive_timer(unsigned long data)  	unsigned int loadadjfreq;  	unsigned int index;  	unsigned long flags; +	bool boosted;  	smp_rmb(); @@ -286,8 +288,9 @@ static void cpufreq_interactive_timer(unsigned long data)  	do_div(cputime_speedadj, delta_time);  	loadadjfreq = (unsigned int)cputime_speedadj * 100;  	cpu_load = loadadjfreq / pcpu->target_freq; +	boosted = boost_val || now < boostpulse_endtime; -	if ((cpu_load >= go_hispeed_load || boost_val) && +	if ((cpu_load >= go_hispeed_load || boosted) &&  	    pcpu->target_freq < hispeed_freq)  		new_freq = hispeed_freq;  	else @@ -327,8 +330,18 @@ static void cpufreq_interactive_timer(unsigned long data)  		}  	} -	pcpu->floor_freq = new_freq; -	pcpu->floor_validate_time = now; +	/* +	 * Update the timestamp for checking whether speed has been held at +	 * or above the selected frequency for a minimum of min_sample_time, +	 * if not boosted to hispeed_freq.  If boosted to hispeed_freq then we +	 * allow the speed to drop as soon as the boostpulse duration expires +	 * (or the indefinite boost is turned off). +	 */ + +	if (!boosted || new_freq > hispeed_freq) { +		pcpu->floor_freq = new_freq; +		pcpu->floor_validate_time = now; +	}  	if (pcpu->target_freq == new_freq) {  		trace_cpufreq_interactive_already( @@ -774,6 +787,7 @@ static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr,  	if (ret < 0)  		return ret; +	boostpulse_endtime = ktime_to_us(ktime_get()) + boostpulse_duration_val;  	trace_cpufreq_interactive_boost("pulse");  	cpufreq_interactive_boost();  	return count; @@ -782,6 +796,29 @@ static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr,  static struct global_attr boostpulse =  	__ATTR(boostpulse, 0200, NULL, store_boostpulse); +static ssize_t show_boostpulse_duration( +	struct kobject *kobj, struct attribute *attr, char *buf) +{ +	return sprintf(buf, "%d\n", boostpulse_duration_val); +} + +static ssize_t store_boostpulse_duration( +	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; + +	boostpulse_duration_val = val; +	return count; +} + +define_one_global_rw(boostpulse_duration); +  static struct attribute *interactive_attributes[] = {  	&target_loads_attr.attr,  	&hispeed_freq_attr.attr, @@ -791,6 +828,7 @@ static struct attribute *interactive_attributes[] = {  	&timer_rate_attr.attr,  	&boost.attr,  	&boostpulse.attr, +	&boostpulse_duration.attr,  	NULL,  };  |