diff options
| author | Jacob Pan <jacob.jun.pan@linux.intel.com> | 2015-05-07 12:03:59 -0400 |
|---|---|---|
| committer | Zhang Rui <rui.zhang@intel.com> | 2015-05-09 01:36:57 -0400 |
| commit | d81861138898ce8d83bc78f0d558ac3984225e2b (patch) | |
| tree | 48762b68a0212357464468ac4026dd148330d724 | |
| parent | f09bfdb6670e08b004959de727eeec73baa753a2 (diff) | |
thermal/powerclamp: fix missing newer package c-states
Package C8 to C10 was introduced in newer Intel CPUs, we need to
include them in the package c-state residency calculation.
Otherwise, idle injection target is not accurately maintained by
the closed control loop.
Also cleaned up the code to make it scale better with large number
of c-states.
Reported-by: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
| -rw-r--r-- | drivers/thermal/intel_powerclamp.c | 80 |
1 files changed, 43 insertions, 37 deletions
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index 9b02d19ce1a4..725718e97a0b 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c | |||
| @@ -206,51 +206,57 @@ static void find_target_mwait(void) | |||
| 206 | 206 | ||
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | struct pkg_cstate_info { | ||
| 210 | bool skip; | ||
| 211 | int msr_index; | ||
| 212 | int cstate_id; | ||
| 213 | }; | ||
| 214 | |||
| 215 | #define PKG_CSTATE_INIT(id) { \ | ||
| 216 | .msr_index = MSR_PKG_C##id##_RESIDENCY, \ | ||
| 217 | .cstate_id = id \ | ||
| 218 | } | ||
| 219 | |||
| 220 | static struct pkg_cstate_info pkg_cstates[] = { | ||
| 221 | PKG_CSTATE_INIT(2), | ||
| 222 | PKG_CSTATE_INIT(3), | ||
| 223 | PKG_CSTATE_INIT(6), | ||
| 224 | PKG_CSTATE_INIT(7), | ||
| 225 | PKG_CSTATE_INIT(8), | ||
| 226 | PKG_CSTATE_INIT(9), | ||
| 227 | PKG_CSTATE_INIT(10), | ||
| 228 | {NULL}, | ||
| 229 | }; | ||
| 230 | |||
| 209 | static bool has_pkg_state_counter(void) | 231 | static bool has_pkg_state_counter(void) |
| 210 | { | 232 | { |
| 211 | u64 tmp; | 233 | u64 val; |
| 212 | return !rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &tmp) || | 234 | struct pkg_cstate_info *info = pkg_cstates; |
| 213 | !rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &tmp) || | 235 | |
| 214 | !rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &tmp) || | 236 | /* check if any one of the counter msrs exists */ |
| 215 | !rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &tmp); | 237 | while (info->msr_index) { |
| 238 | if (!rdmsrl_safe(info->msr_index, &val)) | ||
| 239 | return true; | ||
| 240 | info++; | ||
| 241 | } | ||
| 242 | |||
| 243 | return false; | ||
| 216 | } | 244 | } |
| 217 | 245 | ||
| 218 | static u64 pkg_state_counter(void) | 246 | static u64 pkg_state_counter(void) |
| 219 | { | 247 | { |
| 220 | u64 val; | 248 | u64 val; |
| 221 | u64 count = 0; | 249 | u64 count = 0; |
| 222 | 250 | struct pkg_cstate_info *info = pkg_cstates; | |
| 223 | static bool skip_c2; | 251 | |
| 224 | static bool skip_c3; | 252 | while (info->msr_index) { |
| 225 | static bool skip_c6; | 253 | if (!info->skip) { |
| 226 | static bool skip_c7; | 254 | if (!rdmsrl_safe(info->msr_index, &val)) |
| 227 | 255 | count += val; | |
| 228 | if (!skip_c2) { | 256 | else |
| 229 | if (!rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &val)) | 257 | info->skip = true; |
| 230 | count += val; | 258 | } |
| 231 | else | 259 | info++; |
| 232 | skip_c2 = true; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (!skip_c3) { | ||
| 236 | if (!rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &val)) | ||
| 237 | count += val; | ||
| 238 | else | ||
| 239 | skip_c3 = true; | ||
| 240 | } | ||
| 241 | |||
| 242 | if (!skip_c6) { | ||
| 243 | if (!rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &val)) | ||
| 244 | count += val; | ||
| 245 | else | ||
| 246 | skip_c6 = true; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (!skip_c7) { | ||
| 250 | if (!rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &val)) | ||
| 251 | count += val; | ||
| 252 | else | ||
| 253 | skip_c7 = true; | ||
| 254 | } | 260 | } |
| 255 | 261 | ||
| 256 | return count; | 262 | return count; |
