aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/mcheck
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck')
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 98f2083832eb..41e8e00a6637 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -55,12 +55,24 @@ struct thermal_state {
55 struct _thermal_state package_power_limit; 55 struct _thermal_state package_power_limit;
56 struct _thermal_state core_thresh0; 56 struct _thermal_state core_thresh0;
57 struct _thermal_state core_thresh1; 57 struct _thermal_state core_thresh1;
58 struct _thermal_state pkg_thresh0;
59 struct _thermal_state pkg_thresh1;
58}; 60};
59 61
60/* Callback to handle core threshold interrupts */ 62/* Callback to handle core threshold interrupts */
61int (*platform_thermal_notify)(__u64 msr_val); 63int (*platform_thermal_notify)(__u64 msr_val);
62EXPORT_SYMBOL(platform_thermal_notify); 64EXPORT_SYMBOL(platform_thermal_notify);
63 65
66/* Callback to handle core package threshold_interrupts */
67int (*platform_thermal_package_notify)(__u64 msr_val);
68EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
69
70/* Callback support of rate control, return true, if
71 * callback has rate control */
72bool (*platform_thermal_package_rate_control)(void);
73EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
74
75
64static DEFINE_PER_CPU(struct thermal_state, thermal_state); 76static DEFINE_PER_CPU(struct thermal_state, thermal_state);
65 77
66static atomic_t therm_throt_en = ATOMIC_INIT(0); 78static atomic_t therm_throt_en = ATOMIC_INIT(0);
@@ -195,19 +207,25 @@ static int therm_throt_process(bool new_event, int event, int level)
195 return 0; 207 return 0;
196} 208}
197 209
198static int thresh_event_valid(int event) 210static int thresh_event_valid(int level, int event)
199{ 211{
200 struct _thermal_state *state; 212 struct _thermal_state *state;
201 unsigned int this_cpu = smp_processor_id(); 213 unsigned int this_cpu = smp_processor_id();
202 struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); 214 struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
203 u64 now = get_jiffies_64(); 215 u64 now = get_jiffies_64();
204 216
205 state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1; 217 if (level == PACKAGE_LEVEL)
218 state = (event == 0) ? &pstate->pkg_thresh0 :
219 &pstate->pkg_thresh1;
220 else
221 state = (event == 0) ? &pstate->core_thresh0 :
222 &pstate->core_thresh1;
206 223
207 if (time_before64(now, state->next_check)) 224 if (time_before64(now, state->next_check))
208 return 0; 225 return 0;
209 226
210 state->next_check = now + CHECK_INTERVAL; 227 state->next_check = now + CHECK_INTERVAL;
228
211 return 1; 229 return 1;
212} 230}
213 231
@@ -322,6 +340,39 @@ device_initcall(thermal_throttle_init_device);
322 340
323#endif /* CONFIG_SYSFS */ 341#endif /* CONFIG_SYSFS */
324 342
343static void notify_package_thresholds(__u64 msr_val)
344{
345 bool notify_thres_0 = false;
346 bool notify_thres_1 = false;
347
348 if (!platform_thermal_package_notify)
349 return;
350
351 /* lower threshold check */
352 if (msr_val & THERM_LOG_THRESHOLD0)
353 notify_thres_0 = true;
354 /* higher threshold check */
355 if (msr_val & THERM_LOG_THRESHOLD1)
356 notify_thres_1 = true;
357
358 if (!notify_thres_0 && !notify_thres_1)
359 return;
360
361 if (platform_thermal_package_rate_control &&
362 platform_thermal_package_rate_control()) {
363 /* Rate control is implemented in callback */
364 platform_thermal_package_notify(msr_val);
365 return;
366 }
367
368 /* lower threshold reached */
369 if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
370 platform_thermal_package_notify(msr_val);
371 /* higher threshold reached */
372 if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
373 platform_thermal_package_notify(msr_val);
374}
375
325static void notify_thresholds(__u64 msr_val) 376static void notify_thresholds(__u64 msr_val)
326{ 377{
327 /* check whether the interrupt handler is defined; 378 /* check whether the interrupt handler is defined;
@@ -331,10 +382,12 @@ static void notify_thresholds(__u64 msr_val)
331 return; 382 return;
332 383
333 /* lower threshold reached */ 384 /* lower threshold reached */
334 if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0)) 385 if ((msr_val & THERM_LOG_THRESHOLD0) &&
386 thresh_event_valid(CORE_LEVEL, 0))
335 platform_thermal_notify(msr_val); 387 platform_thermal_notify(msr_val);
336 /* higher threshold reached */ 388 /* higher threshold reached */
337 if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1)) 389 if ((msr_val & THERM_LOG_THRESHOLD1) &&
390 thresh_event_valid(CORE_LEVEL, 1))
338 platform_thermal_notify(msr_val); 391 platform_thermal_notify(msr_val);
339} 392}
340 393
@@ -360,6 +413,8 @@ static void intel_thermal_interrupt(void)
360 413
361 if (this_cpu_has(X86_FEATURE_PTS)) { 414 if (this_cpu_has(X86_FEATURE_PTS)) {
362 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); 415 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
416 /* check violations of package thermal thresholds */
417 notify_package_thresholds(msr_val);
363 therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT, 418 therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
364 THERMAL_THROTTLING_EVENT, 419 THERMAL_THROTTLING_EVENT,
365 PACKAGE_LEVEL); 420 PACKAGE_LEVEL);