diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2015-10-14 19:12:03 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-10-14 19:53:19 -0400 |
commit | 4ef45148701917fbc08a7c05bc6a3bb0c0573047 (patch) | |
tree | 36ed6be3f016d5dd384d71ecdf94d78b7ccc4e05 /drivers/cpufreq | |
parent | 053f56def57bfaef14c97d268ef6bc4ebe952720 (diff) |
cpufreq: intel_pstate: Avoid calculation for max/min
When requested from cpufreq to set policy, look into _pss and get
control values, instead of using max/min perf calculations. These
calculation misses next control state in boundary conditions.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Acked-by: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 041cb4107991..c568226bbcdf 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -163,6 +163,8 @@ struct perf_limits { | |||
163 | int max_sysfs_pct; | 163 | int max_sysfs_pct; |
164 | int min_policy_pct; | 164 | int min_policy_pct; |
165 | int min_sysfs_pct; | 165 | int min_sysfs_pct; |
166 | int max_perf_ctl; | ||
167 | int min_perf_ctl; | ||
166 | }; | 168 | }; |
167 | 169 | ||
168 | static struct perf_limits limits = { | 170 | static struct perf_limits limits = { |
@@ -176,6 +178,8 @@ static struct perf_limits limits = { | |||
176 | .max_sysfs_pct = 100, | 178 | .max_sysfs_pct = 100, |
177 | .min_policy_pct = 0, | 179 | .min_policy_pct = 0, |
178 | .min_sysfs_pct = 0, | 180 | .min_sysfs_pct = 0, |
181 | .max_perf_ctl = 0, | ||
182 | .min_perf_ctl = 0, | ||
179 | }; | 183 | }; |
180 | 184 | ||
181 | #if IS_ENABLED(CONFIG_ACPI) | 185 | #if IS_ENABLED(CONFIG_ACPI) |
@@ -909,12 +913,23 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) | |||
909 | * policy, or by cpu specific default values determined through | 913 | * policy, or by cpu specific default values determined through |
910 | * experimentation. | 914 | * experimentation. |
911 | */ | 915 | */ |
912 | max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); | 916 | if (limits.max_perf_ctl && limits.max_sysfs_pct >= |
913 | *max = clamp_t(int, max_perf_adj, | 917 | limits.max_policy_pct) { |
914 | cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); | 918 | *max = limits.max_perf_ctl; |
919 | } else { | ||
920 | max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), | ||
921 | limits.max_perf)); | ||
922 | *max = clamp_t(int, max_perf_adj, cpu->pstate.min_pstate, | ||
923 | cpu->pstate.turbo_pstate); | ||
924 | } | ||
915 | 925 | ||
916 | min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf)); | 926 | if (limits.min_perf_ctl) { |
917 | *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); | 927 | *min = limits.min_perf_ctl; |
928 | } else { | ||
929 | min_perf = fp_toint(mul_fp(int_tofp(max_perf), | ||
930 | limits.min_perf)); | ||
931 | *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); | ||
932 | } | ||
918 | } | 933 | } |
919 | 934 | ||
920 | static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate, bool force) | 935 | static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate, bool force) |
@@ -1184,6 +1199,12 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) | |||
1184 | 1199 | ||
1185 | static int intel_pstate_set_policy(struct cpufreq_policy *policy) | 1200 | static int intel_pstate_set_policy(struct cpufreq_policy *policy) |
1186 | { | 1201 | { |
1202 | #if IS_ENABLED(CONFIG_ACPI) | ||
1203 | struct cpudata *cpu; | ||
1204 | int i; | ||
1205 | #endif | ||
1206 | pr_debug("intel_pstate: %s max %u policy->max %u\n", __func__, | ||
1207 | policy->cpuinfo.max_freq, policy->max); | ||
1187 | if (!policy->cpuinfo.max_freq) | 1208 | if (!policy->cpuinfo.max_freq) |
1188 | return -ENODEV; | 1209 | return -ENODEV; |
1189 | 1210 | ||
@@ -1196,6 +1217,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
1196 | limits.max_perf_pct = 100; | 1217 | limits.max_perf_pct = 100; |
1197 | limits.max_perf = int_tofp(1); | 1218 | limits.max_perf = int_tofp(1); |
1198 | limits.no_turbo = 0; | 1219 | limits.no_turbo = 0; |
1220 | limits.max_perf_ctl = 0; | ||
1221 | limits.min_perf_ctl = 0; | ||
1199 | return 0; | 1222 | return 0; |
1200 | } | 1223 | } |
1201 | 1224 | ||
@@ -1216,6 +1239,23 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
1216 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); | 1239 | limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); |
1217 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); | 1240 | limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); |
1218 | 1241 | ||
1242 | #if IS_ENABLED(CONFIG_ACPI) | ||
1243 | cpu = all_cpu_data[policy->cpu]; | ||
1244 | for (i = 0; i < cpu->acpi_perf_data.state_count; i++) { | ||
1245 | int control; | ||
1246 | |||
1247 | control = convert_to_native_pstate_format(cpu, i); | ||
1248 | if (control * cpu->pstate.scaling == policy->max) | ||
1249 | limits.max_perf_ctl = control; | ||
1250 | if (control * cpu->pstate.scaling == policy->min) | ||
1251 | limits.min_perf_ctl = control; | ||
1252 | } | ||
1253 | |||
1254 | pr_debug("intel_pstate: max %u policy_max %u perf_ctl [0x%x-0x%x]\n", | ||
1255 | policy->cpuinfo.max_freq, policy->max, limits.min_perf_ctl, | ||
1256 | limits.max_perf_ctl); | ||
1257 | #endif | ||
1258 | |||
1219 | if (hwp_active) | 1259 | if (hwp_active) |
1220 | intel_pstate_hwp_set(); | 1260 | intel_pstate_hwp_set(); |
1221 | 1261 | ||