@@ -69,9 +69,9 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
#endif
static inline bool arch_has_acpi_pdc(void) { return true; }
-static inline void arch_acpi_set_pdc_bits(u32 *buf)
+static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
{
- buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+ *cap |= ACPI_PDC_EST_CAPABILITY_SMP;
}
#ifdef CONFIG_ACPI_NUMA
@@ -100,23 +100,25 @@ static inline bool arch_has_acpi_pdc(void)
c->x86_vendor == X86_VENDOR_CENTAUR);
}
-static inline void arch_acpi_set_pdc_bits(u32 *buf)
+static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
{
struct cpuinfo_x86 *c = &cpu_data(0);
- buf[2] |= ACPI_PDC_C_CAPABILITY_SMP;
+ *cap |= ACPI_PDC_C_CAPABILITY_SMP;
if (cpu_has(c, X86_FEATURE_EST))
- buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
+ *cap |= ACPI_PDC_EST_CAPABILITY_SWSMP;
if (cpu_has(c, X86_FEATURE_ACPI))
- buf[2] |= ACPI_PDC_T_FFH;
+ *cap |= ACPI_PDC_T_FFH;
+ if (cpu_has(c, X86_FEATURE_HWP))
+ *cap |= ACPI_PDC_COLLAB_PROC_PERF;
/*
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
*/
if (!cpu_has(c, X86_FEATURE_MWAIT))
- buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
+ *cap &= ~(ACPI_PDC_C_C2C3_FFH);
}
static inline bool acpi_has_cpu_in_madt(void)
@@ -510,13 +510,12 @@ static void acpi_processor_remove(struct acpi_device *device)
#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)
+static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl,
+ void *context, void **rv)
{
u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";
- u32 capbuf[2];
+ u32 capbuf[2] = { 0 };
+ acpi_status status;
struct acpi_osc_context osc_context = {
.uuid_str = sb_uuid_str,
.rev = 1,
@@ -524,39 +523,43 @@ static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle,
.cap.pointer = capbuf,
};
- if (acpi_hwp_native_thermal_lvt_set)
- return AE_CTRL_TERMINATE;
+ arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);
- capbuf[0] = 0x0000;
- capbuf[1] = 0x1000; /* set bit 12 */
+ if (boot_option_idle_override == IDLE_NOMWAIT)
+ capbuf[OSC_SUPPORT_DWORD] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
- if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
+ status = acpi_run_osc(handle, &osc_context);
+ if (ACPI_SUCCESS(status)) {
if (osc_context.ret.pointer && osc_context.ret.length > 1) {
u32 *capbuf_ret = osc_context.ret.pointer;
- if (capbuf_ret[1] & 0x1000) {
+ if (!acpi_hwp_native_thermal_lvt_set &&
+ capbuf_ret[1] & 0x1000) {
acpi_handle_info(handle,
- "_OSC native thermal LVT Acked\n");
+ "_OSC native thermal LVT Acked\n");
acpi_hwp_native_thermal_lvt_set = true;
}
}
kfree(osc_context.ret.pointer);
}
- return AE_OK;
+ return status;
}
-void __init acpi_early_processor_osc(void)
+acpi_status __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);
- }
+ acpi_status status;
+
+ status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_processor_osc, NULL,
+ NULL, NULL);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc,
+ NULL, NULL);
+
+ return status;
}
#endif
@@ -1317,9 +1317,6 @@ 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
@@ -1335,7 +1332,13 @@ static int __init acpi_bus_init(void)
acpi_sysfs_init();
- acpi_early_processor_set_pdc();
+ status = acpi_early_processor_osc();
+ if (ACPI_FAILURE(status)) {
+ pr_err("_OSC processor control methods failed, trying _PDC\n");
+ acpi_early_processor_set_pdc();
+ } else {
+ pr_err("_OSC methods ran successfully\n");
+ }
/*
* Maybe EC region is required at bus_scan/acpi_get_devices. So it
@@ -156,9 +156,9 @@ static inline void acpi_early_processor_set_pdc(void) {}
#endif
#ifdef CONFIG_X86
-void acpi_early_processor_osc(void);
+acpi_status acpi_early_processor_osc(void);
#else
-static inline void acpi_early_processor_osc(void) {}
+static inline acpi_status acpi_early_processor_osc(void) { return AE_ERROR; }
#endif
/* --------------------------------------------------------------------------
@@ -73,7 +73,7 @@ static void acpi_set_pdc_bits(u32 *buf)
buf[2] = ACPI_PDC_SMP_T_SWCOORD;
/* Twiddle arch-specific bits needed for _PDC */
- arch_acpi_set_pdc_bits(buf);
+ arch_acpi_set_proc_cap_bits(&buf[2]);
}
static struct acpi_object_list *acpi_processor_alloc_pdc(void)
@@ -16,6 +16,7 @@
#define ACPI_PDC_C_C1_FFH (0x0100)
#define ACPI_PDC_C_C2C3_FFH (0x0200)
#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
+#define ACPI_PDC_COLLAB_PROC_PERF (0x1000)
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI 3.0 introduced a new Operating System Capabilities _OSC control method. This method is similar to _PDC, which was marked as deprecated in ACPI 3.0. Prefer using _OSC method over deprecated _PDC in the acpi_bus_init(). In case of the failure of the _OSC, try using _PDC as a fallback. Refactor workaround for HWP introduced in commit a21211672c9a ("ACPI / processor: Request native thermal interrupt handling via _OSC"). This workaround was already using _OSC to work around buggy BIOS in Skylake systems. Change acpi_hwp_native_thermal_lvt_osc() to acpi_processor_osc() and make it more generic. Change arch_acpi_set_pdc_bits() to arch_acpi_set_proc_cap_bits() as the capabilities bitfield is not _PDC specific. Introduce new define ACPI_PDC_COLLAB_PROC_PERF instead of using hard-coded value. Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com> --- arch/ia64/include/asm/acpi.h | 4 +-- arch/x86/include/asm/acpi.h | 12 +++++---- drivers/acpi/acpi_processor.c | 49 +++++++++++++++++++---------------- drivers/acpi/bus.c | 11 +++++--- drivers/acpi/internal.h | 4 +-- drivers/acpi/processor_pdc.c | 2 +- include/acpi/pdc_intel.h | 1 + 7 files changed, 46 insertions(+), 37 deletions(-)