mirror of https://github.com/torvalds/linux.git
Revert "ACPI: processor: idle: Optimize ACPI idle driver registration"
Revert commit 7a8c994cbb ("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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reported-by: Borislav Petkov <bp@alien8.de>
Tested-by: Borislav Petkov (AMD) <bp@alien8.de>
Closes: https://lore.kernel.org/lkml/20251124200019.GIaSS5U9HhsWBotrQZ@fat_crate.local/
This commit is contained in:
parent
1a8b350182
commit
43ff36c4a5
|
|
@ -263,8 +263,6 @@ static int __init acpi_processor_driver_init(void)
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
acpi_processor_register_idle_driver();
|
|
||||||
|
|
||||||
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
||||||
"acpi/cpu-drv:online",
|
"acpi/cpu-drv:online",
|
||||||
acpi_soft_cpu_online, NULL);
|
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(hp_online);
|
||||||
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
|
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
|
||||||
acpi_processor_unregister_idle_driver();
|
|
||||||
driver_unregister(&acpi_processor_driver);
|
driver_unregister(&acpi_processor_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1357,48 +1357,7 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_processor_register_idle_driver(void)
|
static int acpi_processor_registered;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int acpi_processor_power_init(struct acpi_processor *pr)
|
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))
|
if (!acpi_processor_get_power_info(pr))
|
||||||
pr->flags.power_setup_done = 1;
|
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) {
|
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);
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
@ -1426,11 +1400,14 @@ int acpi_processor_power_init(struct acpi_processor *pr)
|
||||||
*/
|
*/
|
||||||
retval = cpuidle_register_device(dev);
|
retval = cpuidle_register_device(dev);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
if (acpi_processor_registered == 0)
|
||||||
|
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||||
|
|
||||||
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
|
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
acpi_processor_registered++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1444,6 +1421,10 @@ int acpi_processor_power_exit(struct acpi_processor *pr)
|
||||||
|
|
||||||
if (pr->flags.power) {
|
if (pr->flags.power) {
|
||||||
cpuidle_unregister_device(dev);
|
cpuidle_unregister_device(dev);
|
||||||
|
acpi_processor_registered--;
|
||||||
|
if (acpi_processor_registered == 0)
|
||||||
|
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||||
|
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_exit(struct acpi_processor *pr);
|
||||||
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
|
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
|
||||||
int acpi_processor_hotplug(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
|
#else
|
||||||
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue