Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpuidle: Init cpuidle only for present CPUs

for_each_possible_cpu() is currently used to initialize cpuidle
in below cpuidle drivers:
drivers/cpuidle/cpuidle-arm.c
drivers/cpuidle/cpuidle-big_little.c
drivers/cpuidle/cpuidle-psci.c
drivers/cpuidle/cpuidle-qcom-spm.c
drivers/cpuidle/cpuidle-riscv-sbi.c

However, in cpu_dev_register_generic(), for_each_present_cpu()
is used to register CPU devices which means the CPU devices are
only registered for present CPUs and not all possible CPUs.

With nosmp or maxcpus=0, only the boot CPU is present, lead
to the failure:

| Failed to register cpuidle device for cpu1

Then rollback to cancel all CPUs' cpuidle registration.

Change for_each_possible_cpu() to for_each_present_cpu() in the
above cpuidle drivers to ensure it only registers cpuidle devices
for CPUs that are actually present.

Fixes: b0c69e1214bc ("drivers: base: Use present CPUs in GENERIC_CPU_DEVICES")
Reviewed-by: Dhruva Gole <d-gole@ti.com>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Tested-by: Yuanjie Yang <quic_yuanjiey@quicinc.com>
Signed-off-by: Jacky Bai <ping.bai@nxp.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://patch.msgid.link/20250307145547.2784821-1-ping.bai@nxp.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jacky Bai and committed by
Rafael J. Wysocki
68cb0139 3332dd12

+10 -10
+4 -4
drivers/cpuidle/cpuidle-arm.c
··· 137 137 /* 138 138 * arm_idle_init - Initializes arm cpuidle driver 139 139 * 140 - * Initializes arm cpuidle driver for all CPUs, if any CPU fails 141 - * to register cpuidle driver then rollback to cancel all CPUs 142 - * registration. 140 + * Initializes arm cpuidle driver for all present CPUs, if any 141 + * CPU fails to register cpuidle driver then rollback to cancel 142 + * all CPUs registration. 143 143 */ 144 144 static int __init arm_idle_init(void) 145 145 { ··· 147 147 struct cpuidle_driver *drv; 148 148 struct cpuidle_device *dev; 149 149 150 - for_each_possible_cpu(cpu) { 150 + for_each_present_cpu(cpu) { 151 151 ret = arm_idle_init_cpu(cpu); 152 152 if (ret) 153 153 goto out_fail;
+1 -1
drivers/cpuidle/cpuidle-big_little.c
··· 148 148 if (!cpumask) 149 149 return -ENOMEM; 150 150 151 - for_each_possible_cpu(cpu) 151 + for_each_present_cpu(cpu) 152 152 if (smp_cpuid_part(cpu) == part_id) 153 153 cpumask_set_cpu(cpu, cpumask); 154 154
+2 -2
drivers/cpuidle/cpuidle-psci.c
··· 400 400 /* 401 401 * psci_idle_probe - Initializes PSCI cpuidle driver 402 402 * 403 - * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails 403 + * Initializes PSCI cpuidle driver for all present CPUs, if any CPU fails 404 404 * to register cpuidle driver then rollback to cancel all CPUs 405 405 * registration. 406 406 */ ··· 410 410 struct cpuidle_driver *drv; 411 411 struct cpuidle_device *dev; 412 412 413 - for_each_possible_cpu(cpu) { 413 + for_each_present_cpu(cpu) { 414 414 ret = psci_idle_init_cpu(&pdev->dev, cpu); 415 415 if (ret) 416 416 goto out_fail;
+1 -1
drivers/cpuidle/cpuidle-qcom-spm.c
··· 135 135 if (ret) 136 136 return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed"); 137 137 138 - for_each_possible_cpu(cpu) { 138 + for_each_present_cpu(cpu) { 139 139 ret = spm_cpuidle_register(&pdev->dev, cpu); 140 140 if (ret && ret != -ENODEV) { 141 141 dev_err(&pdev->dev,
+2 -2
drivers/cpuidle/cpuidle-riscv-sbi.c
··· 529 529 return ret; 530 530 } 531 531 532 - /* Initialize CPU idle driver for each CPU */ 533 - for_each_possible_cpu(cpu) { 532 + /* Initialize CPU idle driver for each present CPU */ 533 + for_each_present_cpu(cpu) { 534 534 ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu); 535 535 if (ret) { 536 536 pr_debug("HART%ld: idle driver init failed\n",