Commit 43ff36c4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Revert "ACPI: processor: idle: Optimize ACPI idle driver registration"



Revert commit 7a8c994c ("ACPI: processor: idle: Optimize ACPI idle
driver registration") because it is reported to introduce a cpuidle
regression leading to a kernel crash on a platform using the ACPI idle
driver.

Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reported-by: default avatarBorislav Petkov <bp@alien8.de>
Tested-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Closes: https://lore.kernel.org/lkml/20251124200019.GIaSS5U9HhsWBotrQZ@fat_crate.local/
parent 1a8b3501
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -263,8 +263,6 @@ static int __init acpi_processor_driver_init(void)
	if (result < 0)
		return result;

	acpi_processor_register_idle_driver();

	result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
				   "acpi/cpu-drv:online",
				   acpi_soft_cpu_online, NULL);
@@ -303,7 +301,6 @@ static void __exit acpi_processor_driver_exit(void)

	cpuhp_remove_state_nocalls(hp_online);
	cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
	acpi_processor_unregister_idle_driver();
	driver_unregister(&acpi_processor_driver);
}

+23 −42
Original line number Diff line number Diff line
@@ -1357,48 +1357,7 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
	return 0;
}

void acpi_processor_register_idle_driver(void)
{
	struct acpi_processor *pr;
	int ret = -ENODEV;
	int cpu;

	/*
	 * Acpi idle driver is used by all possible CPUs.
	 * Install the idle handler by the processor power info of one in them.
	 * Note that we use previously set idle handler will be used on
	 * platforms that only support C1.
	 */
	for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) {
		pr = per_cpu(processors, cpu);
		if (!pr)
			continue;

		ret = acpi_processor_get_power_info(pr);
		if (!ret) {
			pr->flags.power_setup_done = 1;
			acpi_processor_setup_cpuidle_states(pr);
			break;
		}
	}

	if (ret) {
		pr_debug("No ACPI power information from any CPUs.\n");
		return;
	}

	ret = cpuidle_register_driver(&acpi_idle_driver);
	if (ret) {
		pr_debug("register %s failed.\n", acpi_idle_driver.name);
		return;
	}
	pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
}

void acpi_processor_unregister_idle_driver(void)
{
	cpuidle_unregister_driver(&acpi_idle_driver);
}
static int acpi_processor_registered;

int acpi_processor_power_init(struct acpi_processor *pr)
{
@@ -1413,7 +1372,22 @@ int acpi_processor_power_init(struct acpi_processor *pr)
	if (!acpi_processor_get_power_info(pr))
		pr->flags.power_setup_done = 1;

	/*
	 * Install the idle handler if processor power management is supported.
	 * Note that we use previously set idle handler will be used on
	 * platforms that only support C1.
	 */
	if (pr->flags.power) {
		/* Register acpi_idle_driver if not already registered */
		if (!acpi_processor_registered) {
			acpi_processor_setup_cpuidle_states(pr);
			retval = cpuidle_register_driver(&acpi_idle_driver);
			if (retval)
				return retval;
			pr_debug("%s registered with cpuidle\n",
				 acpi_idle_driver.name);
		}

		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
		if (!dev)
			return -ENOMEM;
@@ -1426,11 +1400,14 @@ int acpi_processor_power_init(struct acpi_processor *pr)
		 */
		retval = cpuidle_register_device(dev);
		if (retval) {
			if (acpi_processor_registered == 0)
				cpuidle_unregister_driver(&acpi_idle_driver);

			per_cpu(acpi_cpuidle_device, pr->id) = NULL;
			kfree(dev);
			return retval;
		}
		acpi_processor_registered++;
	}
	return 0;
}
@@ -1444,6 +1421,10 @@ int acpi_processor_power_exit(struct acpi_processor *pr)

	if (pr->flags.power) {
		cpuidle_unregister_device(dev);
		acpi_processor_registered--;
		if (acpi_processor_registered == 0)
			cpuidle_unregister_driver(&acpi_idle_driver);

		kfree(dev);
	}

+0 −2
Original line number Diff line number Diff line
@@ -423,8 +423,6 @@ int acpi_processor_power_init(struct acpi_processor *pr);
int acpi_processor_power_exit(struct acpi_processor *pr);
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
int acpi_processor_hotplug(struct acpi_processor *pr);
void acpi_processor_register_idle_driver(void);
void acpi_processor_unregister_idle_driver(void);
#else
static inline int acpi_processor_power_init(struct acpi_processor *pr)
{