|
@@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device)
|
|
|
}
|
|
|
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
|
|
|
|
|
|
+#ifdef CONFIG_X86
|
|
|
+static bool acpi_hwp_native_thermal_lvt_set;
|
|
|
+static acpi_status __init acpi_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,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (acpi_hwp_native_thermal_lvt_set)
|
|
|
+ return AE_CTRL_TERMINATE;
|
|
|
+
|
|
|
+ capbuf[0] = 0x0000;
|
|
|
+ capbuf[1] = 0x1000; /* set bit 12 */
|
|
|
+
|
|
|
+ if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
|
|
|
+ if (osc_context.ret.pointer && osc_context.ret.length > 1) {
|
|
|
+ u32 *capbuf_ret = osc_context.ret.pointer;
|
|
|
+
|
|
|
+ if (capbuf_ret[1] & 0x1000) {
|
|
|
+ acpi_handle_info(handle,
|
|
|
+ "_OSC native thermal LVT Acked\n");
|
|
|
+ acpi_hwp_native_thermal_lvt_set = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ kfree(osc_context.ret.pointer);
|
|
|
+ }
|
|
|
+
|
|
|
+ return AE_OK;
|
|
|
+}
|
|
|
+
|
|
|
+void __init acpi_early_processor_osc(void)
|
|
|
+{
|
|
|
+ if (boot_cpu_has(X86_FEATURE_HWP)) {
|
|
|
+ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
|
|
+ ACPI_UINT32_MAX,
|
|
|
+ acpi_hwp_native_thermal_lvt_osc,
|
|
|
+ NULL, NULL, NULL);
|
|
|
+ acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
|
|
|
+ acpi_hwp_native_thermal_lvt_osc,
|
|
|
+ NULL, NULL);
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* The following ACPI IDs are known to be suitable for representing as
|
|
|
* processor devices.
|