Commit cd923966 authored by Jonathan Cameron's avatar Jonathan Cameron Committed by Catalin Marinas
Browse files

ACPI: processor: Move checks and availability of acpi_processor earlier



Make the per_cpu(processors, cpu) entries available earlier so that
they are available in arch_register_cpu() as ARM64 will need access
to the acpi_handle to distinguish between acpi_processor_add()
and earlier registration attempts (which will fail as _STA cannot
be checked).

Reorder the remove flow to clear this per_cpu() after
arch_unregister_cpu() has completed, allowing it to be used in
there as well.

Note that on x86 for the CPU hotplug case, the pr->id prior to
acpi_map_cpu() may be invalid. Thus the per_cpu() structures
must be initialized after that call or after checking the ID
is valid (not hotplug path).

Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarGavin Shan <gshan@redhat.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20240529133446.28446-7-Jonathan.Cameron@huawei.com


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 47ec9b41
Loading
Loading
Loading
Loading
+52 −36
Original line number Diff line number Diff line
@@ -183,8 +183,38 @@ static void __init acpi_pcc_cpufreq_init(void) {}
#endif /* CONFIG_X86 */

/* Initialization */
static DEFINE_PER_CPU(void *, processor_device_array);

static int acpi_processor_set_per_cpu(struct acpi_processor *pr,
				      struct acpi_device *device)
{
	BUG_ON(pr->id >= nr_cpu_ids);

	/*
	 * Buggy BIOS check.
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
		dev_warn(&device->dev,
			 "BIOS reported wrong ACPI id %d for the processor\n",
			 pr->id);
		return -EINVAL;
	}
	/*
	 * processor_device_array is not cleared on errors to allow buggy BIOS
	 * checks.
	 */
	per_cpu(processor_device_array, pr->id) = device;
	per_cpu(processors, pr->id) = pr;

	return 0;
}

#ifdef CONFIG_ACPI_HOTPLUG_CPU
static int acpi_processor_hotadd_init(struct acpi_processor *pr)
static int acpi_processor_hotadd_init(struct acpi_processor *pr,
				      struct acpi_device *device)
{
	int ret;

@@ -198,8 +228,16 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
	if (ret)
		goto out;

	ret = acpi_processor_set_per_cpu(pr, device);
	if (ret) {
		acpi_unmap_cpu(pr->id);
		goto out;
	}

	ret = arch_register_cpu(pr->id);
	if (ret) {
		/* Leave the processor device array in place to detect buggy bios */
		per_cpu(processors, pr->id) = NULL;
		acpi_unmap_cpu(pr->id);
		goto out;
	}
@@ -217,7 +255,8 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
	return ret;
}
#else
static inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
static inline int acpi_processor_hotadd_init(struct acpi_processor *pr,
					     struct acpi_device *device)
{
	return -ENODEV;
}
@@ -232,6 +271,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
	acpi_status status = AE_OK;
	static int cpu0_initialized;
	unsigned long long value;
	int ret;

	acpi_processor_errata();

@@ -315,12 +355,12 @@ static int acpi_processor_get_info(struct acpi_device *device)
	 *  NOTE: Even if the processor has a cpuid, it may not be present
	 *  because cpuid <-> apicid mapping is persistent now.
	 */
	if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) {
		int ret = acpi_processor_hotadd_init(pr);

	if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id))
		ret = acpi_processor_hotadd_init(pr, device);
	else
		ret = acpi_processor_set_per_cpu(pr, device);
	if (ret)
		return ret;
	}

	/*
	 * On some boxes several processors use the same processor bus id.
@@ -365,8 +405,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
 * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
 * Such things have to be put in and set up by the processor driver's .probe().
 */
static DEFINE_PER_CPU(void *, processor_device_array);

static int acpi_processor_add(struct acpi_device *device,
					const struct acpi_device_id *id)
{
@@ -395,28 +433,6 @@ static int acpi_processor_add(struct acpi_device *device,
	if (result) /* Processor is not physically present or unavailable */
		goto err_clear_driver_data;

	BUG_ON(pr->id >= nr_cpu_ids);

	/*
	 * Buggy BIOS check.
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
		dev_warn(&device->dev,
			"BIOS reported wrong ACPI id %d for the processor\n",
			pr->id);
		/* Give up, but do not abort the namespace scan. */
		goto err_clear_driver_data;
	}
	/*
	 * processor_device_array is not cleared on errors to allow buggy BIOS
	 * checks.
	 */
	per_cpu(processor_device_array, pr->id) = device;
	per_cpu(processors, pr->id) = pr;

	dev = get_cpu_device(pr->id);
	if (!dev) {
		result = -ENODEV;
@@ -470,10 +486,6 @@ static void acpi_processor_remove(struct acpi_device *device)
	device_release_driver(pr->dev);
	acpi_unbind_one(pr->dev);

	/* Clean up. */
	per_cpu(processor_device_array, pr->id) = NULL;
	per_cpu(processors, pr->id) = NULL;

	cpu_maps_update_begin();
	cpus_write_lock();

@@ -481,6 +493,10 @@ static void acpi_processor_remove(struct acpi_device *device)
	arch_unregister_cpu(pr->id);
	acpi_unmap_cpu(pr->id);

	/* Clean up. */
	per_cpu(processor_device_array, pr->id) = NULL;
	per_cpu(processors, pr->id) = NULL;

	cpus_write_unlock();
	cpu_maps_update_done();