| From d33bd88ac0ebb49e7f7c8f29a8c7ee9eae85d765 Mon Sep 17 00:00:00 2001 |
| From: Jiayi Li <lijiayi@kylinos.cn> |
| Date: Mon, 21 Jul 2025 11:26:06 +0800 |
| Subject: ACPI: processor: perflib: Fix initial _PPC limit application |
| |
| From: Jiayi Li <lijiayi@kylinos.cn> |
| |
| commit d33bd88ac0ebb49e7f7c8f29a8c7ee9eae85d765 upstream. |
| |
| If the BIOS sets a _PPC frequency limit upfront, it will fail to take |
| effect due to a call ordering issue. Namely, freq_qos_update_request() |
| is called before freq_qos_add_request() for the given request causing |
| the constraint update to be ignored. The call sequence in question is |
| as follows: |
| |
| cpufreq_policy_online() |
| acpi_cpufreq_cpu_init() |
| acpi_processor_register_performance() |
| acpi_processor_get_performance_info() |
| acpi_processor_get_platform_limit() |
| freq_qos_update_request(&perflib_req) <- inactive QoS request |
| blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| CPUFREQ_CREATE_POLICY) |
| acpi_processor_notifier() |
| acpi_processor_ppc_init() |
| freq_qos_add_request(&perflib_req) <- QoS request activation |
| |
| Address this by adding an acpi_processor_get_platform_limit() call |
| to acpi_processor_ppc_init(), after the perflib_req activation via |
| freq_qos_add_request(), which causes the initial _PPC limit to be |
| picked up as appropriate. However, also ensure that the _PPC limit |
| will not be picked up in the cases when the cpufreq driver does not |
| call acpi_processor_register_performance() by adding a pr->performance |
| check to the related_cpus loop in acpi_processor_ppc_init(). |
| |
| Fixes: d15ce412737a ("ACPI: cpufreq: Switch to QoS requests instead of cpufreq notifier") |
| Signed-off-by: Jiayi Li <lijiayi@kylinos.cn> |
| Link: https://patch.msgid.link/20250721032606.3459369-1-lijiayi@kylinos.cn |
| [ rjw: Consolidate pr-related checks in acpi_processor_ppc_init() ] |
| [ rjw: Subject and changelog adjustments ] |
| Cc: 5.4+ <stable@vger.kernel.org> # 5.4+: 2d8b39a62a5d ACPI: processor: Avoid NULL pointer dereferences at init time |
| Cc: 5.4+ <stable@vger.kernel.org> # 5.4+: 3000ce3c52f8 cpufreq: Use per-policy frequency QoS |
| Cc: 5.4+ <stable@vger.kernel.org> # 5.4+: a1bb46c36ce3 ACPI: processor: Add QoS requests for all CPUs |
| Cc: 5.4+ <stable@vger.kernel.org> # 5.4+ |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/acpi/processor_perflib.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/acpi/processor_perflib.c |
| +++ b/drivers/acpi/processor_perflib.c |
| @@ -174,11 +174,14 @@ void acpi_processor_ppc_init(struct cpuf |
| { |
| unsigned int cpu; |
| |
| + if (ignore_ppc == 1) |
| + return; |
| + |
| for_each_cpu(cpu, policy->related_cpus) { |
| struct acpi_processor *pr = per_cpu(processors, cpu); |
| int ret; |
| |
| - if (!pr) |
| + if (!pr || !pr->performance) |
| continue; |
| |
| /* |
| @@ -194,6 +197,11 @@ void acpi_processor_ppc_init(struct cpuf |
| if (ret < 0) |
| pr_err("Failed to add freq constraint for CPU%d (%d)\n", |
| cpu, ret); |
| + |
| + ret = acpi_processor_get_platform_limit(pr); |
| + if (ret) |
| + pr_err("Failed to update freq constraint for CPU%d (%d)\n", |
| + cpu, ret); |
| } |
| } |
| |