Skip to content

Commit 7a8c994

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(). Signed-off-by: Huisong Li <lihuisong@huawei.com> Link: https://patch.msgid.link/20250728070612.1260859-3-lihuisong@huawei.com [ rjw: Added missing inline modifiers ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 11b3de1 commit 7a8c994

3 files changed

Lines changed: 53 additions & 23 deletions

File tree

drivers/acpi/processor_driver.c

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

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

302304
cpuhp_remove_state_nocalls(hp_online);
303305
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
306+
acpi_processor_unregister_idle_driver();
304307
driver_unregister(&acpi_processor_driver);
305308
}
306309

drivers/acpi/processor_idle.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,48 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
13601360
return 0;
13611361
}
13621362

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

13651406
int acpi_processor_power_init(struct acpi_processor *pr)
13661407
{
@@ -1375,22 +1416,7 @@ int acpi_processor_power_init(struct acpi_processor *pr)
13751416
if (!acpi_processor_get_power_info(pr))
13761417
pr->flags.power_setup_done = 1;
13771418

1378-
/*
1379-
* Install the idle handler if processor power management is supported.
1380-
* Note that we use previously set idle handler will be used on
1381-
* platforms that only support C1.
1382-
*/
13831419
if (pr->flags.power) {
1384-
/* Register acpi_idle_driver if not already registered */
1385-
if (!acpi_processor_registered) {
1386-
acpi_processor_setup_cpuidle_states(pr);
1387-
retval = cpuidle_register_driver(&acpi_idle_driver);
1388-
if (retval)
1389-
return retval;
1390-
pr_debug("%s registered with cpuidle\n",
1391-
acpi_idle_driver.name);
1392-
}
1393-
13941420
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
13951421
if (!dev)
13961422
return -ENOMEM;
@@ -1403,14 +1429,11 @@ int acpi_processor_power_init(struct acpi_processor *pr)
14031429
*/
14041430
retval = cpuidle_register_device(dev);
14051431
if (retval) {
1406-
if (acpi_processor_registered == 0)
1407-
cpuidle_unregister_driver(&acpi_idle_driver);
14081432

14091433
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
14101434
kfree(dev);
14111435
return retval;
14121436
}
1413-
acpi_processor_registered++;
14141437
}
14151438
return 0;
14161439
}
@@ -1424,10 +1447,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr)
14241447

14251448
if (pr->flags.power) {
14261449
cpuidle_unregister_device(dev);
1427-
acpi_processor_registered--;
1428-
if (acpi_processor_registered == 0)
1429-
cpuidle_unregister_driver(&acpi_idle_driver);
1430-
14311450
kfree(dev);
14321451
}
14331452

include/acpi/processor.h

Lines changed: 8 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
{
@@ -443,6 +445,12 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr)
443445
{
444446
return -ENODEV;
445447
}
448+
static inline void acpi_processor_register_idle_driver(void)
449+
{
450+
}
451+
static inline void acpi_processor_unregister_idle_driver(void)
452+
{
453+
}
446454
#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
447455

448456
/* in processor_thermal.c */

0 commit comments

Comments
 (0)