Skip to content

Commit 13ebeef

Browse files
LiHuiSong1rafaeljw
authored andcommitted
ACPI: processor: idle: Optimize ACPI idle driver registration
Currently, the ACPI idle driver is registered from within a CPU hotplug callback. Although this didn't cause any functional issues, this is questionable and confusing. And it is better to register the cpuidle driver when all of the CPUs have been brought up. So add a new function to initialize acpi_idle_driver based on the power management information of an available CPU and register cpuidle driver in acpi_processor_driver_init(). This commit has four changes under the commit 7a8c994 (ACPI: processor: idle: Optimize ACPI idle driver registration): 1) move acpi_processor_register_idle_driver() ahead of the driver_register(). 2) add acpi_processor_cstate_first_run_checks() before calling acpi_processor_get_power_info(). 3) squash the commit 9d68320 (ACPI: processor: idle: Fix function defined but not used warning) into this change. 4) use for_each_possible_cpu(cpu) to scan all possible cpus. Signed-off-by: Huisong Li <lihuisong@huawei.com> Tested-by: Borislav Petkov (AMD) <bp@alien8.de> [ rjw: New comment edits, changelog tweak ] Link: https://patch.msgid.link/20251223100914.2407069-2-lihuisong@huawei.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 9ace475 commit 13ebeef

3 files changed

Lines changed: 54 additions & 24 deletions

File tree

drivers/acpi/processor_driver.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ static int __init acpi_processor_driver_init(void)
259259
acpi_processor_ignore_ppc_init();
260260
}
261261

262+
acpi_processor_register_idle_driver();
263+
262264
result = driver_register(&acpi_processor_driver);
263265
if (result < 0)
264-
return result;
266+
goto unregister_idle_drv;
265267

266268
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
267269
"acpi/cpu-drv:online",
@@ -283,8 +285,13 @@ static int __init acpi_processor_driver_init(void)
283285
acpi_idle_rescan_dead_smt_siblings();
284286

285287
return 0;
288+
286289
err:
287290
driver_unregister(&acpi_processor_driver);
291+
292+
unregister_idle_drv:
293+
acpi_processor_unregister_idle_driver();
294+
288295
return result;
289296
}
290297

@@ -302,6 +309,7 @@ static void __exit acpi_processor_driver_exit(void)
302309
cpuhp_remove_state_nocalls(hp_online);
303310
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
304311
driver_unregister(&acpi_processor_driver);
312+
acpi_processor_unregister_idle_driver();
305313
}
306314

307315
module_init(acpi_processor_driver_init);

drivers/acpi/processor_idle.c

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,49 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
13471347
return 0;
13481348
}
13491349

1350-
static int acpi_processor_registered;
1350+
void acpi_processor_register_idle_driver(void)
1351+
{
1352+
struct acpi_processor *pr;
1353+
int ret = -ENODEV;
1354+
int cpu;
1355+
1356+
/*
1357+
* ACPI idle driver is used by all possible CPUs.
1358+
* Use the processor power info of one in them to set up idle states.
1359+
* Note that the existing idle handler will be used on platforms that
1360+
* only support C1.
1361+
*/
1362+
for_each_possible_cpu(cpu) {
1363+
pr = per_cpu(processors, cpu);
1364+
if (!pr)
1365+
continue;
1366+
1367+
acpi_processor_cstate_first_run_checks();
1368+
ret = acpi_processor_get_power_info(pr);
1369+
if (!ret) {
1370+
pr->flags.power_setup_done = 1;
1371+
acpi_processor_setup_cpuidle_states(pr);
1372+
break;
1373+
}
1374+
}
1375+
1376+
if (ret) {
1377+
pr_debug("No ACPI power information from any CPUs.\n");
1378+
return;
1379+
}
1380+
1381+
ret = cpuidle_register_driver(&acpi_idle_driver);
1382+
if (ret) {
1383+
pr_debug("register %s failed.\n", acpi_idle_driver.name);
1384+
return;
1385+
}
1386+
pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
1387+
}
1388+
1389+
void acpi_processor_unregister_idle_driver(void)
1390+
{
1391+
cpuidle_unregister_driver(&acpi_idle_driver);
1392+
}
13511393

13521394
int acpi_processor_power_init(struct acpi_processor *pr)
13531395
{
@@ -1362,22 +1404,7 @@ int acpi_processor_power_init(struct acpi_processor *pr)
13621404
if (!acpi_processor_get_power_info(pr))
13631405
pr->flags.power_setup_done = 1;
13641406

1365-
/*
1366-
* Install the idle handler if processor power management is supported.
1367-
* Note that we use previously set idle handler will be used on
1368-
* platforms that only support C1.
1369-
*/
13701407
if (pr->flags.power) {
1371-
/* Register acpi_idle_driver if not already registered */
1372-
if (!acpi_processor_registered) {
1373-
acpi_processor_setup_cpuidle_states(pr);
1374-
retval = cpuidle_register_driver(&acpi_idle_driver);
1375-
if (retval)
1376-
return retval;
1377-
pr_debug("%s registered with cpuidle\n",
1378-
acpi_idle_driver.name);
1379-
}
1380-
13811408
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
13821409
if (!dev)
13831410
return -ENOMEM;
@@ -1390,14 +1417,11 @@ int acpi_processor_power_init(struct acpi_processor *pr)
13901417
*/
13911418
retval = cpuidle_register_device(dev);
13921419
if (retval) {
1393-
if (acpi_processor_registered == 0)
1394-
cpuidle_unregister_driver(&acpi_idle_driver);
13951420

13961421
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
13971422
kfree(dev);
13981423
return retval;
13991424
}
1400-
acpi_processor_registered++;
14011425
}
14021426
return 0;
14031427
}
@@ -1411,10 +1435,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr)
14111435

14121436
if (pr->flags.power) {
14131437
cpuidle_unregister_device(dev);
1414-
acpi_processor_registered--;
1415-
if (acpi_processor_registered == 0)
1416-
cpuidle_unregister_driver(&acpi_idle_driver);
1417-
14181438
kfree(dev);
14191439
}
14201440

include/acpi/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ 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);
426428
#else
427429
static inline int acpi_processor_power_init(struct acpi_processor *pr)
428430
{

0 commit comments

Comments
 (0)