Skip to content

Commit 43ff36c

Browse files
committed
Revert "ACPI: processor: idle: Optimize ACPI idle driver registration"
Revert commit 7a8c994 ("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/
1 parent 1a8b350 commit 43ff36c

3 files changed

Lines changed: 23 additions & 47 deletions

File tree

drivers/acpi/processor_driver.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,6 @@ static int __init acpi_processor_driver_init(void)
263263
if (result < 0)
264264
return result;
265265

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

304302
cpuhp_remove_state_nocalls(hp_online);
305303
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
306-
acpi_processor_unregister_idle_driver();
307304
driver_unregister(&acpi_processor_driver);
308305
}
309306

drivers/acpi/processor_idle.c

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,48 +1357,7 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
13571357
return 0;
13581358
}
13591359

1360-
void acpi_processor_register_idle_driver(void)
1361-
{
1362-
struct acpi_processor *pr;
1363-
int ret = -ENODEV;
1364-
int cpu;
1365-
1366-
/*
1367-
* Acpi idle driver is used by all possible CPUs.
1368-
* Install the idle handler by the processor power info of one in them.
1369-
* Note that we use previously set idle handler will be used on
1370-
* platforms that only support C1.
1371-
*/
1372-
for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) {
1373-
pr = per_cpu(processors, cpu);
1374-
if (!pr)
1375-
continue;
1376-
1377-
ret = acpi_processor_get_power_info(pr);
1378-
if (!ret) {
1379-
pr->flags.power_setup_done = 1;
1380-
acpi_processor_setup_cpuidle_states(pr);
1381-
break;
1382-
}
1383-
}
1384-
1385-
if (ret) {
1386-
pr_debug("No ACPI power information from any CPUs.\n");
1387-
return;
1388-
}
1389-
1390-
ret = cpuidle_register_driver(&acpi_idle_driver);
1391-
if (ret) {
1392-
pr_debug("register %s failed.\n", acpi_idle_driver.name);
1393-
return;
1394-
}
1395-
pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
1396-
}
1397-
1398-
void acpi_processor_unregister_idle_driver(void)
1399-
{
1400-
cpuidle_unregister_driver(&acpi_idle_driver);
1401-
}
1360+
static int acpi_processor_registered;
14021361

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

1375+
/*
1376+
* Install the idle handler if processor power management is supported.
1377+
* Note that we use previously set idle handler will be used on
1378+
* platforms that only support C1.
1379+
*/
14161380
if (pr->flags.power) {
1381+
/* Register acpi_idle_driver if not already registered */
1382+
if (!acpi_processor_registered) {
1383+
acpi_processor_setup_cpuidle_states(pr);
1384+
retval = cpuidle_register_driver(&acpi_idle_driver);
1385+
if (retval)
1386+
return retval;
1387+
pr_debug("%s registered with cpuidle\n",
1388+
acpi_idle_driver.name);
1389+
}
1390+
14171391
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
14181392
if (!dev)
14191393
return -ENOMEM;
@@ -1426,11 +1400,14 @@ int acpi_processor_power_init(struct acpi_processor *pr)
14261400
*/
14271401
retval = cpuidle_register_device(dev);
14281402
if (retval) {
1403+
if (acpi_processor_registered == 0)
1404+
cpuidle_unregister_driver(&acpi_idle_driver);
14291405

14301406
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
14311407
kfree(dev);
14321408
return retval;
14331409
}
1410+
acpi_processor_registered++;
14341411
}
14351412
return 0;
14361413
}
@@ -1444,6 +1421,10 @@ int acpi_processor_power_exit(struct acpi_processor *pr)
14441421

14451422
if (pr->flags.power) {
14461423
cpuidle_unregister_device(dev);
1424+
acpi_processor_registered--;
1425+
if (acpi_processor_registered == 0)
1426+
cpuidle_unregister_driver(&acpi_idle_driver);
1427+
14471428
kfree(dev);
14481429
}
14491430

include/acpi/processor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,6 @@ int acpi_processor_power_init(struct acpi_processor *pr);
423423
int acpi_processor_power_exit(struct acpi_processor *pr);
424424
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
425425
int acpi_processor_hotplug(struct acpi_processor *pr);
426-
void acpi_processor_register_idle_driver(void);
427-
void acpi_processor_unregister_idle_driver(void);
428426
#else
429427
static inline int acpi_processor_power_init(struct acpi_processor *pr)
430428
{

0 commit comments

Comments
 (0)