Skip to content

Commit 1826907

Browse files
committed
Merge tag 'pm+acpi-4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
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
2 parents 4e19fd9 + 8fbd4ad commit 1826907

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

arch/x86/kernel/cpu/mcheck/therm_throt.c

+3
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ static void intel_thermal_interrupt(void)
384384
{
385385
__u64 msr_val;
386386

387+
if (static_cpu_has(X86_FEATURE_HWP))
388+
wrmsrl_safe(MSR_HWP_STATUS, 0);
389+
387390
rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
388391

389392
/* Check for violation of core thermal thresholds*/

drivers/acpi/acpi_processor.c

+52
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device)
491491
}
492492
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
493493

494+
#ifdef CONFIG_X86
495+
static bool acpi_hwp_native_thermal_lvt_set;
496+
static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle,
497+
u32 lvl,
498+
void *context,
499+
void **rv)
500+
{
501+
u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
502+
u32 capbuf[2];
503+
struct acpi_osc_context osc_context = {
504+
.uuid_str = sb_uuid_str,
505+
.rev = 1,
506+
.cap.length = 8,
507+
.cap.pointer = capbuf,
508+
};
509+
510+
if (acpi_hwp_native_thermal_lvt_set)
511+
return AE_CTRL_TERMINATE;
512+
513+
capbuf[0] = 0x0000;
514+
capbuf[1] = 0x1000; /* set bit 12 */
515+
516+
if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
517+
if (osc_context.ret.pointer && osc_context.ret.length > 1) {
518+
u32 *capbuf_ret = osc_context.ret.pointer;
519+
520+
if (capbuf_ret[1] & 0x1000) {
521+
acpi_handle_info(handle,
522+
"_OSC native thermal LVT Acked\n");
523+
acpi_hwp_native_thermal_lvt_set = true;
524+
}
525+
}
526+
kfree(osc_context.ret.pointer);
527+
}
528+
529+
return AE_OK;
530+
}
531+
532+
void __init acpi_early_processor_osc(void)
533+
{
534+
if (boot_cpu_has(X86_FEATURE_HWP)) {
535+
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
536+
ACPI_UINT32_MAX,
537+
acpi_hwp_native_thermal_lvt_osc,
538+
NULL, NULL, NULL);
539+
acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
540+
acpi_hwp_native_thermal_lvt_osc,
541+
NULL, NULL);
542+
}
543+
}
544+
#endif
545+
494546
/*
495547
* The following ACPI IDs are known to be suitable for representing as
496548
* processor devices.

drivers/acpi/bus.c

+3
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,9 @@ static int __init acpi_bus_init(void)
10191019
goto error1;
10201020
}
10211021

1022+
/* Set capability bits for _OSC under processor scope */
1023+
acpi_early_processor_osc();
1024+
10221025
/*
10231026
* _OSC method may exist in module level code,
10241027
* so it must be run after ACPI_FULL_INITIALIZATION

drivers/acpi/internal.h

+6
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ void acpi_early_processor_set_pdc(void);
145145
static inline void acpi_early_processor_set_pdc(void) {}
146146
#endif
147147

148+
#ifdef CONFIG_X86
149+
void acpi_early_processor_osc(void);
150+
#else
151+
static inline void acpi_early_processor_osc(void) {}
152+
#endif
153+
148154
/* --------------------------------------------------------------------------
149155
Embedded Controller
150156
-------------------------------------------------------------------------- */

0 commit comments

Comments
 (0)