diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2013-05-17 19:42:01 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2013-06-12 21:59:14 -0400 |
commit | 25cdce170d28092e8e162f36702be3308973b19d (patch) | |
tree | 7a9a51759bca561984bfaae1170c922ad5cf11c7 /arch/x86 | |
parent | c240a539df4e2d50f86e2f31813ff6b7334cd493 (diff) |
x86, mcheck, therm_throt: Process package thresholds
Added callback registration for package threshold reports. Also added
a callback to check the rate control implemented in callback or not.
If there is no rate control implemented, then there is a default rate
control similar to core threshold notification by delaying for
CHECK_INTERVAL (5 minutes) between reports.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/mce.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/therm_throt.c | 63 |
2 files changed, 66 insertions, 4 deletions
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index fa5f71e021d5..16a214557a58 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -214,6 +214,13 @@ void mce_log_therm_throt_event(__u64 status); | |||
214 | /* Interrupt Handler for core thermal thresholds */ | 214 | /* Interrupt Handler for core thermal thresholds */ |
215 | extern int (*platform_thermal_notify)(__u64 msr_val); | 215 | extern int (*platform_thermal_notify)(__u64 msr_val); |
216 | 216 | ||
217 | /* Interrupt Handler for package thermal thresholds */ | ||
218 | extern int (*platform_thermal_package_notify)(__u64 msr_val); | ||
219 | |||
220 | /* Callback support of rate control, return true, if | ||
221 | * callback has rate control */ | ||
222 | extern bool (*platform_thermal_package_rate_control)(void); | ||
223 | |||
217 | #ifdef CONFIG_X86_THERMAL_VECTOR | 224 | #ifdef CONFIG_X86_THERMAL_VECTOR |
218 | extern void mcheck_intel_therm_init(void); | 225 | extern void mcheck_intel_therm_init(void); |
219 | #else | 226 | #else |
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 47a1870279aa..4131c0393594 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -54,12 +54,24 @@ struct thermal_state { | |||
54 | struct _thermal_state package_power_limit; | 54 | struct _thermal_state package_power_limit; |
55 | struct _thermal_state core_thresh0; | 55 | struct _thermal_state core_thresh0; |
56 | struct _thermal_state core_thresh1; | 56 | struct _thermal_state core_thresh1; |
57 | struct _thermal_state pkg_thresh0; | ||
58 | struct _thermal_state pkg_thresh1; | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | /* Callback to handle core threshold interrupts */ | 61 | /* Callback to handle core threshold interrupts */ |
60 | int (*platform_thermal_notify)(__u64 msr_val); | 62 | int (*platform_thermal_notify)(__u64 msr_val); |
61 | EXPORT_SYMBOL(platform_thermal_notify); | 63 | EXPORT_SYMBOL(platform_thermal_notify); |
62 | 64 | ||
65 | /* Callback to handle core package threshold_interrupts */ | ||
66 | int (*platform_thermal_package_notify)(__u64 msr_val); | ||
67 | EXPORT_SYMBOL_GPL(platform_thermal_package_notify); | ||
68 | |||
69 | /* Callback support of rate control, return true, if | ||
70 | * callback has rate control */ | ||
71 | bool (*platform_thermal_package_rate_control)(void); | ||
72 | EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control); | ||
73 | |||
74 | |||
63 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); | 75 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); |
64 | 76 | ||
65 | static atomic_t therm_throt_en = ATOMIC_INIT(0); | 77 | static atomic_t therm_throt_en = ATOMIC_INIT(0); |
@@ -203,19 +215,25 @@ static int therm_throt_process(bool new_event, int event, int level) | |||
203 | return 0; | 215 | return 0; |
204 | } | 216 | } |
205 | 217 | ||
206 | static int thresh_event_valid(int event) | 218 | static int thresh_event_valid(int level, int event) |
207 | { | 219 | { |
208 | struct _thermal_state *state; | 220 | struct _thermal_state *state; |
209 | unsigned int this_cpu = smp_processor_id(); | 221 | unsigned int this_cpu = smp_processor_id(); |
210 | struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); | 222 | struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); |
211 | u64 now = get_jiffies_64(); | 223 | u64 now = get_jiffies_64(); |
212 | 224 | ||
213 | state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1; | 225 | if (level == PACKAGE_LEVEL) |
226 | state = (event == 0) ? &pstate->pkg_thresh0 : | ||
227 | &pstate->pkg_thresh1; | ||
228 | else | ||
229 | state = (event == 0) ? &pstate->core_thresh0 : | ||
230 | &pstate->core_thresh1; | ||
214 | 231 | ||
215 | if (time_before64(now, state->next_check)) | 232 | if (time_before64(now, state->next_check)) |
216 | return 0; | 233 | return 0; |
217 | 234 | ||
218 | state->next_check = now + CHECK_INTERVAL; | 235 | state->next_check = now + CHECK_INTERVAL; |
236 | |||
219 | return 1; | 237 | return 1; |
220 | } | 238 | } |
221 | 239 | ||
@@ -321,6 +339,39 @@ device_initcall(thermal_throttle_init_device); | |||
321 | 339 | ||
322 | #endif /* CONFIG_SYSFS */ | 340 | #endif /* CONFIG_SYSFS */ |
323 | 341 | ||
342 | static void notify_package_thresholds(__u64 msr_val) | ||
343 | { | ||
344 | bool notify_thres_0 = false; | ||
345 | bool notify_thres_1 = false; | ||
346 | |||
347 | if (!platform_thermal_package_notify) | ||
348 | return; | ||
349 | |||
350 | /* lower threshold check */ | ||
351 | if (msr_val & THERM_LOG_THRESHOLD0) | ||
352 | notify_thres_0 = true; | ||
353 | /* higher threshold check */ | ||
354 | if (msr_val & THERM_LOG_THRESHOLD1) | ||
355 | notify_thres_1 = true; | ||
356 | |||
357 | if (!notify_thres_0 && !notify_thres_1) | ||
358 | return; | ||
359 | |||
360 | if (platform_thermal_package_rate_control && | ||
361 | platform_thermal_package_rate_control()) { | ||
362 | /* Rate control is implemented in callback */ | ||
363 | platform_thermal_package_notify(msr_val); | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | /* lower threshold reached */ | ||
368 | if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0)) | ||
369 | platform_thermal_package_notify(msr_val); | ||
370 | /* higher threshold reached */ | ||
371 | if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1)) | ||
372 | platform_thermal_package_notify(msr_val); | ||
373 | } | ||
374 | |||
324 | static void notify_thresholds(__u64 msr_val) | 375 | static void notify_thresholds(__u64 msr_val) |
325 | { | 376 | { |
326 | /* check whether the interrupt handler is defined; | 377 | /* check whether the interrupt handler is defined; |
@@ -330,10 +381,12 @@ static void notify_thresholds(__u64 msr_val) | |||
330 | return; | 381 | return; |
331 | 382 | ||
332 | /* lower threshold reached */ | 383 | /* lower threshold reached */ |
333 | if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0)) | 384 | if ((msr_val & THERM_LOG_THRESHOLD0) && |
385 | thresh_event_valid(CORE_LEVEL, 0)) | ||
334 | platform_thermal_notify(msr_val); | 386 | platform_thermal_notify(msr_val); |
335 | /* higher threshold reached */ | 387 | /* higher threshold reached */ |
336 | if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1)) | 388 | if ((msr_val & THERM_LOG_THRESHOLD1) && |
389 | thresh_event_valid(CORE_LEVEL, 1)) | ||
337 | platform_thermal_notify(msr_val); | 390 | platform_thermal_notify(msr_val); |
338 | } | 391 | } |
339 | 392 | ||
@@ -359,6 +412,8 @@ static void intel_thermal_interrupt(void) | |||
359 | 412 | ||
360 | if (this_cpu_has(X86_FEATURE_PTS)) { | 413 | if (this_cpu_has(X86_FEATURE_PTS)) { |
361 | rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); | 414 | rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); |
415 | /* check violations of package thermal thresholds */ | ||
416 | notify_package_thresholds(msr_val); | ||
362 | therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT, | 417 | therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT, |
363 | THERMAL_THROTTLING_EVENT, | 418 | THERMAL_THROTTLING_EVENT, |
364 | PACKAGE_LEVEL); | 419 | PACKAGE_LEVEL); |