Re: [PATCH] ACPI: processor: Add acpi_processor_start() back to parse _CPC tables before CPU online
From: zhenglifeng (A)
Date: Wed Aug 26 2026 - 21:40:08 EST
Hi Pengjie,
On 8/26/2026 3:59 PM, Pengjie Zhang wrote:
> Hi Lifeng,
>
> On 1/20/2026 7:32 PM, Lifeng Zheng wrote:
>> Currently, if boot with maxcpus less than NR_CPUS, the cppc_cpufreq driver
>> will fail to register. Because it requires the domain information of all
>> possible CPUs to construct shared_cpu_map, which shows the CPUs that share
>> the same domain.
>>
>> Commit c1385c1f0ba3 ("ACPI: processor: Simplify initial onlining to use
>> same path for cold and hotplug") removes probe() of acpi_processor_driver
>> and makes acpi_cppc_processor_probe() only being called the first time CPU
>> goes online. This means that CPUs that haven't yet gone online will not
>> have pre-parsed _CPC objects and causes cppc_cpufreq driver register fail.
>>
>> Add acpi_processor_start() back as the probe() callback of
>> acpi_processor_driver and call acpi_cppc_processor_probe() in it to make
>> sure all _CPC tables will be parsed when acpi_processor_driver registered.
>>
>> Fixes: c1385c1f0ba3 ("ACPI: processor: Simplify initial onlining to use same path for cold and hotplug")
>> Signed-off-by: Lifeng Zheng <zhenglifeng1@xxxxxxxxxx>
>> ---
>> drivers/acpi/processor_driver.c | 30 ++++++++++++++++++++++++++----
>> 1 file changed, 26 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
>> index 65e779be64ff..c8b4daf580b0 100644
>> --- a/drivers/acpi/processor_driver.c
>> +++ b/drivers/acpi/processor_driver.c
>> @@ -33,6 +33,7 @@ MODULE_AUTHOR("Paul Diefenbaugh");
>> MODULE_DESCRIPTION("ACPI Processor Driver");
>> MODULE_LICENSE("GPL");
>> +static int acpi_processor_start(struct device *dev);
>> static int acpi_processor_stop(struct device *dev);
>> static const struct acpi_device_id processor_device_ids[] = {
>> @@ -46,6 +47,7 @@ static struct device_driver acpi_processor_driver = {
>> .name = "processor",
>> .bus = &cpu_subsys,
>> .acpi_match_table = processor_device_ids,
>> + .probe = acpi_processor_start,
>> .remove = acpi_processor_stop,
>> };
>> @@ -162,10 +164,6 @@ static int __acpi_processor_start(struct acpi_device *device)
>> if (!pr)
>> return -ENODEV;
>> - result = acpi_cppc_processor_probe(pr);
>> - if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
>> - dev_dbg(&device->dev, "CPPC data invalid or not present\n");
>> -
>> if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
>> acpi_processor_power_init(pr);
>> @@ -192,6 +190,30 @@ static int __acpi_processor_start(struct acpi_device *device)
>> return result;
>> }
>> +static int acpi_processor_start(struct device *dev)
>> +{
>> + struct acpi_device *device = ACPI_COMPANION(dev);
>> + struct acpi_processor *pr;
>> + int result;
>> +
>> + if (!device)
>> + return -ENODEV;
>> +
>> + pr = acpi_driver_data(device);
>> + if (!pr)
>> + return -ENODEV;
>> +
>> + /* Protect against concurrent CPU hotplug operations */
>> + cpu_hotplug_disable();
>> + result = acpi_cppc_processor_probe(pr);
>> + cpu_hotplug_enable();
>> +
>> + if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
>> + dev_dbg(&device->dev, "CPPC data invalid or not present\n");
>> +
>> + return 0;
>> +}
>> +
>> static int acpi_processor_stop(struct device *dev)
>> {
>> struct acpi_device *device = ACPI_COMPANION(dev);
> I reproduced the issue described by this patch on the latest kernel at
> commit 45c13f3f9e3bb15f.
>
> On my system, CPU0 and CPU1 belong to the same software-coordinated
> frequency domain. After booting with maxcpus=1, CPU1 is present but
> offline, and its CPC descriptor is not parsed.
>
> Consequently, acpi_get_psd_map() skips CPU1 and constructs an
> incomplete shared_cpu_map containing only CPU0.
>
> When CPU1 is subsequently brought online:
>
> echo 1 > /sys/devices/system/cpu/cpu1/online
>
> the cpufreq core creates an overlapping policy and attempts to create
> the existing cpu0/cpufreq symbolic link again, resulting in the
> following warnings:
> ...
> sysfs_warn_dup
> sysfs_do_create_link_sd
> sysfs_create_link
> add_cpu_dev_symlink
> cpufreq_policy_online
> cpufreq_online
> cpuhp_cpufreq_online
> ...
> processor cpu0: cpufreq symlink creation failed
>
> freq_qos_add_request() called for active request
> WARNING: kernel/power/qos.c:658 at freq_qos_add_request
>
> The affected CPU masks are also inconsistent:
>
> $ cat /sys/devices/system/cpu/cpu0/cpufreq/affected_cpus
> 0
>
> $ cat /sys/devices/system/cpu/cpu1/cpufreq/affected_cpus
> 0 1
>
> After applying this patch on top of commit 45c13f3f9e3bb15f, the CPC
> descriptors are parsed before the CPUs are brought online. The
> shared_cpu_map is constructed correctly, and CPU1 can be brought
> online without triggering the duplicate sysfs link or active QoS
> request warnings.
>
> This patch fixes the issue in my testing. so,
>
> Tested-by: Pengjie Zhang <zhangpengjie2@xxxxxxxxxx>
> Reviewed-by: Pengjie Zhang <zhangpengjie2@xxxxxxxxxx>
>
Thanks for the testing!