]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.8.5/cpufreq-conservative-fix-next-frequency-selection.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.8.5 / cpufreq-conservative-fix-next-frequency-selection.patch
1 From abb6627910a1e783c8e034b35b7c80e5e7f98f41 Mon Sep 17 00:00:00 2001
2 From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
3 Date: Wed, 12 Oct 2016 21:47:03 +0200
4 Subject: cpufreq: conservative: Fix next frequency selection
5
6 From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
7
8 commit abb6627910a1e783c8e034b35b7c80e5e7f98f41 upstream.
9
10 Commit d352cf47d93e (cpufreq: conservative: Do not use transition
11 notifications) overlooked the case when the "frequency step" used
12 by the conservative governor is small relative to the distances
13 between the available frequencies and broke the algorithm by
14 using policy->cur instead of the previously requested frequency
15 when computing the next one.
16
17 As a result, the governor may not be able to go outside of a narrow
18 range between two consecutive available frequencies.
19
20 Fix the problem by making the governor save the previously requested
21 frequency and select the next one relative that value (unless it is
22 out of range, in which case policy->cur will be used instead).
23
24 Fixes: d352cf47d93e (cpufreq: conservative: Do not use transition notifications)
25 Link: https://bugzilla.kernel.org/show_bug.cgi?id=177171
26 Reported-and-tested-by: Aleksey Rybalkin <aleksey@rybalkin.org>
27 Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
28 Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
29 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30
31 ---
32 drivers/cpufreq/cpufreq_conservative.c | 19 ++++++++++++++++---
33 1 file changed, 16 insertions(+), 3 deletions(-)
34
35 --- a/drivers/cpufreq/cpufreq_conservative.c
36 +++ b/drivers/cpufreq/cpufreq_conservative.c
37 @@ -17,6 +17,7 @@
38 struct cs_policy_dbs_info {
39 struct policy_dbs_info policy_dbs;
40 unsigned int down_skip;
41 + unsigned int requested_freq;
42 };
43
44 static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
45 @@ -61,6 +62,7 @@ static unsigned int cs_dbs_timer(struct
46 {
47 struct policy_dbs_info *policy_dbs = policy->governor_data;
48 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
49 + unsigned int requested_freq = dbs_info->requested_freq;
50 struct dbs_data *dbs_data = policy_dbs->dbs_data;
51 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
52 unsigned int load = dbs_update(policy);
53 @@ -72,10 +74,16 @@ static unsigned int cs_dbs_timer(struct
54 if (cs_tuners->freq_step == 0)
55 goto out;
56
57 + /*
58 + * If requested_freq is out of range, it is likely that the limits
59 + * changed in the meantime, so fall back to current frequency in that
60 + * case.
61 + */
62 + if (requested_freq > policy->max || requested_freq < policy->min)
63 + requested_freq = policy->cur;
64 +
65 /* Check for frequency increase */
66 if (load > dbs_data->up_threshold) {
67 - unsigned int requested_freq = policy->cur;
68 -
69 dbs_info->down_skip = 0;
70
71 /* if we are already at full speed then break out early */
72 @@ -83,8 +91,11 @@ static unsigned int cs_dbs_timer(struct
73 goto out;
74
75 requested_freq += get_freq_target(cs_tuners, policy);
76 + if (requested_freq > policy->max)
77 + requested_freq = policy->max;
78
79 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
80 + dbs_info->requested_freq = requested_freq;
81 goto out;
82 }
83
84 @@ -95,7 +106,7 @@ static unsigned int cs_dbs_timer(struct
85
86 /* Check for frequency decrease */
87 if (load < cs_tuners->down_threshold) {
88 - unsigned int freq_target, requested_freq = policy->cur;
89 + unsigned int freq_target;
90 /*
91 * if we cannot reduce the frequency anymore, break out early
92 */
93 @@ -109,6 +120,7 @@ static unsigned int cs_dbs_timer(struct
94 requested_freq = policy->min;
95
96 __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
97 + dbs_info->requested_freq = requested_freq;
98 }
99
100 out:
101 @@ -287,6 +299,7 @@ static void cs_start(struct cpufreq_poli
102 struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
103
104 dbs_info->down_skip = 0;
105 + dbs_info->requested_freq = policy->cur;
106 }
107
108 static struct dbs_governor cs_governor = {