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 e6c8e6fb45f..604f06af6dc 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c | |||
@@ -94,11 +94,12 @@ static unsigned long timer_rate; | |||
94 | #define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE | 94 | #define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE |
95 | static unsigned long above_hispeed_delay_val; | 95 | static unsigned long above_hispeed_delay_val; |
96 | 96 | ||
97 | /* | 97 | /* Non-zero means indefinite speed boost active */ |
98 | * Non-zero means longer-term speed boost active. | ||
99 | */ | ||
100 | |||
101 | static int boost_val; | 98 | static int boost_val; |
99 | /* Duration of a boot pulse in usecs */ | ||
100 | static int boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; | ||
101 | /* End time of boost pulse in ktime converted to usecs */ | ||
102 | static u64 boostpulse_endtime; | ||
102 | 103 | ||
103 | static bool governidle; | 104 | static bool governidle; |
104 | module_param(governidle, bool, S_IWUSR | S_IRUGO); | 105 | module_param(governidle, bool, S_IWUSR | S_IRUGO); |
@@ -267,6 +268,7 @@ static void cpufreq_interactive_timer(unsigned long data) | |||
267 | unsigned int loadadjfreq; | 268 | unsigned int loadadjfreq; |
268 | unsigned int index; | 269 | unsigned int index; |
269 | unsigned long flags; | 270 | unsigned long flags; |
271 | bool boosted; | ||
270 | 272 | ||
271 | smp_rmb(); | 273 | smp_rmb(); |
272 | 274 | ||
@@ -285,8 +287,9 @@ static void cpufreq_interactive_timer(unsigned long data) | |||
285 | do_div(cputime_speedadj, delta_time); | 287 | do_div(cputime_speedadj, delta_time); |
286 | loadadjfreq = (unsigned int)cputime_speedadj * 100; | 288 | loadadjfreq = (unsigned int)cputime_speedadj * 100; |
287 | cpu_load = loadadjfreq / pcpu->target_freq; | 289 | cpu_load = loadadjfreq / pcpu->target_freq; |
290 | boosted = boost_val || now < boostpulse_endtime; | ||
288 | 291 | ||
289 | if ((cpu_load >= go_hispeed_load || boost_val) && | 292 | if ((cpu_load >= go_hispeed_load || boosted) && |
290 | pcpu->target_freq < hispeed_freq) | 293 | pcpu->target_freq < hispeed_freq) |
291 | new_freq = hispeed_freq; | 294 | new_freq = hispeed_freq; |
292 | else | 295 | else |
@@ -326,8 +329,18 @@ static void cpufreq_interactive_timer(unsigned long data) | |||
326 | } | 329 | } |
327 | } | 330 | } |
328 | 331 | ||
329 | pcpu->floor_freq = new_freq; | 332 | /* |
330 | pcpu->floor_validate_time = now; | 333 | * Update the timestamp for checking whether speed has been held at |
334 | * or above the selected frequency for a minimum of min_sample_time, | ||
335 | * if not boosted to hispeed_freq. If boosted to hispeed_freq then we | ||
336 | * allow the speed to drop as soon as the boostpulse duration expires | ||
337 | * (or the indefinite boost is turned off). | ||
338 | */ | ||
339 | |||
340 | if (!boosted || new_freq > hispeed_freq) { | ||
341 | pcpu->floor_freq = new_freq; | ||
342 | pcpu->floor_validate_time = now; | ||
343 | } | ||
331 | 344 | ||
332 | if (pcpu->target_freq == new_freq) { | 345 | if (pcpu->target_freq == new_freq) { |
333 | trace_cpufreq_interactive_already( | 346 | trace_cpufreq_interactive_already( |
@@ -773,6 +786,7 @@ static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr, | |||
773 | if (ret < 0) | 786 | if (ret < 0) |
774 | return ret; | 787 | return ret; |
775 | 788 | ||
789 | boostpulse_endtime = ktime_to_us(ktime_get()) + boostpulse_duration_val; | ||
776 | trace_cpufreq_interactive_boost("pulse"); | 790 | trace_cpufreq_interactive_boost("pulse"); |
777 | cpufreq_interactive_boost(); | 791 | cpufreq_interactive_boost(); |
778 | return count; | 792 | return count; |
@@ -781,6 +795,29 @@ static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr, | |||
781 | static struct global_attr boostpulse = | 795 | static struct global_attr boostpulse = |
782 | __ATTR(boostpulse, 0200, NULL, store_boostpulse); | 796 | __ATTR(boostpulse, 0200, NULL, store_boostpulse); |
783 | 797 | ||
798 | static ssize_t show_boostpulse_duration( | ||
799 | struct kobject *kobj, struct attribute *attr, char *buf) | ||
800 | { | ||
801 | return sprintf(buf, "%d\n", boostpulse_duration_val); | ||
802 | } | ||
803 | |||
804 | static ssize_t store_boostpulse_duration( | ||
805 | struct kobject *kobj, struct attribute *attr, const char *buf, | ||
806 | size_t count) | ||
807 | { | ||
808 | int ret; | ||
809 | unsigned long val; | ||
810 | |||
811 | ret = kstrtoul(buf, 0, &val); | ||
812 | if (ret < 0) | ||
813 | return ret; | ||
814 | |||
815 | boostpulse_duration_val = val; | ||
816 | return count; | ||
817 | } | ||
818 | |||
819 | define_one_global_rw(boostpulse_duration); | ||
820 | |||
784 | static struct attribute *interactive_attributes[] = { | 821 | static struct attribute *interactive_attributes[] = { |
785 | &target_loads_attr.attr, | 822 | &target_loads_attr.attr, |
786 | &hispeed_freq_attr.attr, | 823 | &hispeed_freq_attr.attr, |
@@ -790,6 +827,7 @@ static struct attribute *interactive_attributes[] = { | |||
790 | &timer_rate_attr.attr, | 827 | &timer_rate_attr.attr, |
791 | &boost.attr, | 828 | &boost.attr, |
792 | &boostpulse.attr, | 829 | &boostpulse.attr, |
830 | &boostpulse_duration.attr, | ||
793 | NULL, | 831 | NULL, |
794 | }; | 832 | }; |
795 | 833 | ||