summarylogtreecommitdiffstats
path: root/t460s_acpi.patch
blob: e12ea2ab74718989a446f790d2f3881212c7f90e (plain)
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
    -------------------------------------------------------------------------- */
--