Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1826907c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull power management and ACPI fix from Rafael J. Wysocki:
 "Just one fix for a nasty boot failure on some systems based on Intel
  Skylake that shipped with broken firmware where enabling
  hardware-coordinated P-states management (HWP) causes a faulty
  interrupt handler in SMM to be invoked and crash the system (Srinivas
  Pandruvada)"

* tag 'pm+acpi-4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / processor: Request native thermal interrupt handling via _OSC
parents 4e19fd93 8fbd4ade
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -384,6 +384,9 @@ static void intel_thermal_interrupt(void)
{
	__u64 msr_val;

	if (static_cpu_has(X86_FEATURE_HWP))
		wrmsrl_safe(MSR_HWP_STATUS, 0);

	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);

	/* Check for violation of core thermal thresholds*/
+52 −0
Original line number Diff line number Diff line
@@ -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.
+3 −0
Original line number Diff line number Diff line
@@ -1019,6 +1019,9 @@ static int __init acpi_bus_init(void)
		goto error1;
	}

	/* Set capability bits for _OSC under processor scope */
	acpi_early_processor_osc();

	/*
	 * _OSC method may exist in module level code,
	 * so it must be run after ACPI_FULL_INITIALIZATION
+6 −0
Original line number Diff line number Diff line
@@ -145,6 +145,12 @@ void acpi_early_processor_set_pdc(void);
static inline void acpi_early_processor_set_pdc(void) {}
#endif

#ifdef CONFIG_X86
void acpi_early_processor_osc(void);
#else
static inline void acpi_early_processor_osc(void) {}
#endif

/* --------------------------------------------------------------------------
                                  Embedded Controller
   -------------------------------------------------------------------------- */