1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
@@ -, +, @@
- It is freezing in BIOS when tries to handle thermal interrupt, which
- With SMM handling thermal we loose all the reporting features of
- Some thermal drivers like x86-package-temp driver depends on the thermal
- The HWP interrupts are useful for debugging and tuning performance
---
arch/x86/kernel/cpu/mcheck/therm_throt.c | 3 +++
drivers/acpi/acpi_processor.c | 44 +++++++++++++++++++++++++++++++-
drivers/acpi/bus.c | 3 +++
drivers/acpi/internal.h | 2 ++
4 files changed, 51 insertions(+), 1 deletion(-)
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ a/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -385,6 +385,9 @@ static void intel_thermal_interrupt(void)
{
__u64 msr_val;
+ if (static_cpu_has_safe(X86_FEATURE_HWP))
+ wrmsrl_safe(MSR_HWP_STATUS, 0);
+
rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
/* Check for violation of core thermal thresholds*/
--- a/drivers/acpi/acpi_processor.c
+++ a/drivers/acpi/acpi_processor.c
@@ -391,7 +391,6 @@ static int acpi_processor_add(struct acpi_device *device,
if (pr->id >= setup_max_cpus && pr->id != 0)
return 0;
#endif
-
BUG_ON(pr->id >= nr_cpu_ids);
/*
@@ -491,6 +490,49 @@ static void acpi_processor_remove(struct acpi_device *device)
}
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+static bool acpi_hwp_native_thermal_lvt_set;
+static acpi_status acpi_set_hwp_native_thermal_lvt_osc(acpi_handle handle,
+ u32 lvl, void *context,
+ void **rv)
+{
+ u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
+ u32 capbuf[2];
+ struct acpi_osc_context osc_context = {
+ .uuid_str = sb_uuid_str,
+ .rev = 1,
+ .cap.length = 8,
+ .cap.pointer = capbuf,
+ };
+
+ printk(KERN_ERR "%s \n", __func__);
+ if (acpi_hwp_native_thermal_lvt_set)
+ return AE_OK;
+
+ if (!static_cpu_has_safe(X86_FEATURE_HWP))
+ return AE_OK;
+
+ capbuf[0] = 0x0000;
+ capbuf[1] = 0x1000; /* set bit 12 */
+
+ if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
+ printk(KERN_ERR "%s successful \n", __func__);
+ acpi_hwp_native_thermal_lvt_set = true;
+ kfree(osc_context.ret.pointer);
+ }
+
+ return AE_OK;
+}
+
+void acpi_early_processor_set_osc(void)
+{
+ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_set_hwp_native_thermal_lvt_osc,
+ NULL, NULL,NULL);
+ acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
+ acpi_set_hwp_native_thermal_lvt_osc, NULL, NULL);
+}
+
/*
* The following ACPI IDs are known to be suitable for representing as
* processor devices.
--- a/drivers/acpi/bus.c
+++ a/drivers/acpi/bus.c
@@ -1005,6 +1005,9 @@ static int __init acpi_bus_init(void)
goto error1;
}
+ /* Set capability bits for _OSC under processor scope */
+ acpi_early_processor_set_osc();
+
/*
* _OSC method may exist in module level code,
* so it must be run after ACPI_FULL_INITIALIZATION
--- a/drivers/acpi/internal.h
+++ a/drivers/acpi/internal.h
@@ -138,6 +138,8 @@ void acpi_early_processor_set_pdc(void);
static inline void acpi_early_processor_set_pdc(void) {}
#endif
+void acpi_early_processor_set_osc(void);
+
/* --------------------------------------------------------------------------
Embedded Controller
-------------------------------------------------------------------------- */
--
|