Commit 9bd0c413 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-processor'

Merge ACPI processor driver changes for 6.6-rc1:

 - Support obtaining physical CPU ID from MADT on LoongArch (Bibo Mao).

 - Convert ACPI CPU initialization to using _OSC instead of _PDC that
   has been depreceted since 2018 and dropped from the specification in
   ACPI 6.5 (Michal Wilczynski, Rafael Wysocki).

* acpi-processor:
  ACPI: processor: LoongArch: Get physical ID from MADT
  ACPI: processor: Refine messages in acpi_early_processor_control_setup()
  ACPI: processor: Remove acpi_hwp_native_thermal_lvt_osc()
  ACPI: processor: Use _OSC to convey OSPM processor support information
  ACPI: processor: Introduce acpi_processor_osc()
  ACPI: processor: Set CAP_SMP_T_SWCOORD in arch_acpi_set_proc_cap_bits()
  ACPI: processor: Clear C_C2C3_FFH and C_C1_FFH in arch_acpi_set_proc_cap_bits()
  ACPI: processor: Rename ACPI_PDC symbols
  ACPI: processor: Refactor arch_acpi_set_pdc_bits()
  ACPI: processor: Move processor_physically_present() to acpi_processor.c
  ACPI: processor: Move MWAIT quirk out of acpi_processor.c
parents e921f8c8 f6fcf03c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@

#ifdef __KERNEL__

#include <acpi/pdc_intel.h>
#include <acpi/proc_cap_intel.h>

#include <linux/init.h>
#include <linux/numa.h>
@@ -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_PROC_CAP_EST_CAPABILITY_SMP;
}

#ifdef CONFIG_ACPI_NUMA
+16 −8
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
 *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *  Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
 */
#include <acpi/pdc_intel.h>
#include <acpi/proc_cap_intel.h>

#include <asm/numa.h>
#include <asm/fixmap.h>
@@ -102,23 +102,31 @@ 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_PROC_CAP_C_CAPABILITY_SMP;

	/* Enable coordination with firmware's _TSD info */
	*cap |= ACPI_PROC_CAP_SMP_T_SWCOORD;

	if (cpu_has(c, X86_FEATURE_EST))
		buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
		*cap |= ACPI_PROC_CAP_EST_CAPABILITY_SWSMP;

	if (cpu_has(c, X86_FEATURE_ACPI))
		buf[2] |= ACPI_PDC_T_FFH;
		*cap |= ACPI_PROC_CAP_T_FFH;

	if (cpu_has(c, X86_FEATURE_HWP))
		*cap |= ACPI_PROC_CAP_COLLAB_PROC_PERF;

	/*
	 * If mwait/monitor is unsupported, C2/C3_FFH will be disabled
	 * If mwait/monitor is unsupported, C_C1_FFH and
	 * C2/C3_FFH will be disabled.
	 */
	if (!cpu_has(c, X86_FEATURE_MWAIT))
		buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
	if (!cpu_has(c, X86_FEATURE_MWAIT) ||
	    boot_option_idle_override == IDLE_NOMWAIT)
		*cap &= ~(ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH);
}

static inline bool acpi_has_cpu_in_madt(void)
+4 −4
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#include <asm/acpi.h>
#include <acpi/pdc_intel.h>
#include <acpi/proc_cap_intel.h>
#include <acpi/processor.h>
#include <xen/interface/platform.h>
#endif
@@ -288,17 +288,17 @@ static bool __init xen_check_mwait(void)

	native_cpuid(&ax, &bx, &cx, &dx);

	/* Ask the Hypervisor whether to clear ACPI_PDC_C_C2C3_FFH. If so,
	/* Ask the Hypervisor whether to clear ACPI_PROC_CAP_C_C2C3_FFH. If so,
	 * don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3.
	 */
	buf[0] = ACPI_PDC_REVISION_ID;
	buf[1] = 1;
	buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP);
	buf[2] = (ACPI_PROC_CAP_C_CAPABILITY_SMP | ACPI_PROC_CAP_EST_CAPABILITY_SWSMP);

	set_xen_guest_handle(op.u.set_pminfo.pdc, buf);

	if ((HYPERVISOR_platform_op(&op) == 0) &&
	    (buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) {
	    (buf[2] & (ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH))) {
		cpuid_leaf5_ecx_val = cx;
		cpuid_leaf5_edx_val = dx;
	}
+92 −32
Original line number Diff line number Diff line
@@ -9,9 +9,11 @@
 * Copyright (C) 2013, Intel Corporation
 *                     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 */
#define pr_fmt(fmt) "ACPI: " fmt

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -21,6 +23,8 @@

#include <asm/cpu.h>

#include <xen/xen.h>

#include "internal.h"

DEFINE_PER_CPU(struct acpi_processor *, processors);
@@ -508,54 +512,110 @@ 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)
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
bool __init processor_physically_present(acpi_handle handle)
{
	int cpuid, type;
	u32 acpi_id;
	acpi_status status;
	acpi_object_type acpi_type;
	unsigned long long tmp;
	union acpi_object object = {};
	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };

	status = acpi_get_type(handle, &acpi_type);
	if (ACPI_FAILURE(status))
		return false;

	switch (acpi_type) {
	case ACPI_TYPE_PROCESSOR:
		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
		if (ACPI_FAILURE(status))
			return false;
		acpi_id = object.processor.proc_id;
		break;
	case ACPI_TYPE_DEVICE:
		status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
					       NULL, &tmp);
		if (ACPI_FAILURE(status))
			return false;
		acpi_id = tmp;
		break;
	default:
		return false;
	}

	if (xen_initial_domain())
		/*
		 * When running as a Xen dom0 the number of processors Linux
		 * sees can be different from the real number of processors on
		 * the system, and we still need to execute _PDC or _OSC for
		 * all of them.
		 */
		return xen_processor_present(acpi_id);

	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
	cpuid = acpi_get_cpuid(handle, type, acpi_id);

	return !invalid_logical_cpuid(cpuid);
}

/* vendor specific UUID indicating an Intel platform */
static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953";

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] = {};
	struct acpi_osc_context osc_context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_status status;

	if (acpi_hwp_native_thermal_lvt_set)
		return AE_CTRL_TERMINATE;
	if (!processor_physically_present(handle))
		return AE_OK;

	capbuf[0] = 0x0000;
	capbuf[1] = 0x1000; /* set bit 12 */
	arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);

	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;
	status = acpi_run_osc(handle, &osc_context);
	if (ACPI_FAILURE(status))
		return status;

			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)
static bool __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,
	acpi_status status;

	acpi_proc_quirk_mwait_check();

	status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
				     ACPI_UINT32_MAX, acpi_processor_osc, NULL,
				     NULL, NULL);
	if (ACPI_FAILURE(status))
		return false;

	status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc,
				  NULL, NULL);
	if (ACPI_FAILURE(status))
		return false;

	return true;
}

void __init acpi_early_processor_control_setup(void)
{
	if (acpi_early_processor_osc()) {
		pr_info("_OSC evaluated successfully for all CPUs\n");
	} else {
		pr_info("_OSC evaluation for CPUs failed, trying _PDC\n");
		acpi_early_processor_set_pdc();
	}
}
#endif
+1 −4
Original line number Diff line number Diff line
@@ -1322,9 +1322,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
@@ -1340,7 +1337,7 @@ static int __init acpi_bus_init(void)

	acpi_sysfs_init();

	acpi_early_processor_set_pdc();
	acpi_early_processor_control_setup();

	/*
	 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
Loading