aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2013-05-17 19:42:01 -0400
committerZhang Rui <rui.zhang@intel.com>2013-06-12 21:59:14 -0400
commit25cdce170d28092e8e162f36702be3308973b19d (patch)
tree7a9a51759bca561984bfaae1170c922ad5cf11c7 /arch/x86
parentc240a539df4e2d50f86e2f31813ff6b7334cd493 (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.h7
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c63
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 */
215extern int (*platform_thermal_notify)(__u64 msr_val); 215extern int (*platform_thermal_notify)(__u64 msr_val);
216 216
217/* Interrupt Handler for package thermal thresholds */
218extern int (*platform_thermal_package_notify)(__u64 msr_val);
219
220/* Callback support of rate control, return true, if
221 * callback has rate control */
222extern bool (*platform_thermal_package_rate_control)(void);
223
217#ifdef CONFIG_X86_THERMAL_VECTOR 224#ifdef CONFIG_X86_THERMAL_VECTOR
218extern void mcheck_intel_therm_init(void); 225extern 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 */
60int (*platform_thermal_notify)(__u64 msr_val); 62int (*platform_thermal_notify)(__u64 msr_val);
61EXPORT_SYMBOL(platform_thermal_notify); 63EXPORT_SYMBOL(platform_thermal_notify);
62 64
65/* Callback to handle core package threshold_interrupts */
66int (*platform_thermal_package_notify)(__u64 msr_val);
67EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
68
69/* Callback support of rate control, return true, if
70 * callback has rate control */
71bool (*platform_thermal_package_rate_control)(void);
72EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
73
74
63static DEFINE_PER_CPU(struct thermal_state, thermal_state); 75static DEFINE_PER_CPU(struct thermal_state, thermal_state);
64 76
65static atomic_t therm_throt_en = ATOMIC_INIT(0); 77static 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
206static int thresh_event_valid(int event) 218static 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
342static 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
324static void notify_thresholds(__u64 msr_val) 375static 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);