* [PATCH v2 0/2] cpufreq: cppc: Add update_limits support for Highest Performance changes
@ 2026-05-08 11:19 Xueqin Luo
2026-05-08 11:19 ` [PATCH v2 1/2] cpufreq: cppc: Refactor autonomous perf limit programming Xueqin Luo
2026-05-08 11:19 ` [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
0 siblings, 2 replies; 7+ messages in thread
From: Xueqin Luo @ 2026-05-08 11:19 UTC (permalink / raw)
To: rafael, viresh.kumar, zhanjie9, zhenglifeng1, pierre.gondois,
sumitg, linux-pm, linux-kernel
Cc: Xueqin Luo
Hi,
This series adds update_limits support for cppc_cpufreq to handle
dynamic Highest Performance updates triggered by ACPI Notify(0x85).
According to the ACPI CPPC specification, OSPM is required to
re-evaluate the Highest Performance register when Notify(0x85)
is received for a processor device.
Patch 1 refactors the autonomous performance limit programming
logic into a helper function.
Patch 2 implements cppc_cpufreq_update_limits() to refresh the
cached highest_perf capability and update autonomous performance
bounds when needed.
Changes in v2:
Fix incorrect variable name causing build issue
Thanks.
Xueqin Luo (2):
cpufreq: cppc: Refactor autonomous perf limit programming
cpufreq: cppc: Add update_limits support for Highest Performance
changes
drivers/cpufreq/cppc_cpufreq.c | 89 +++++++++++++++++++++++++++++-----
1 file changed, 76 insertions(+), 13 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] cpufreq: cppc: Refactor autonomous perf limit programming
2026-05-08 11:19 [PATCH v2 0/2] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
@ 2026-05-08 11:19 ` Xueqin Luo
2026-05-08 11:19 ` [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
1 sibling, 0 replies; 7+ messages in thread
From: Xueqin Luo @ 2026-05-08 11:19 UTC (permalink / raw)
To: rafael, viresh.kumar, zhanjie9, zhenglifeng1, pierre.gondois,
sumitg, linux-pm, linux-kernel
Cc: Xueqin Luo
Factor out the autonomous performance limit update logic into
cppc_cpufreq_set_autonomous_perf().
There should be no functional change as a result of this patch.
Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
---
drivers/cpufreq/cppc_cpufreq.c | 44 ++++++++++++++++++++++++----------
1 file changed, 31 insertions(+), 13 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 7e7f9dfb7a24..7ddf4296c474 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -843,6 +843,36 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
return 0;
}
+/**
+ * cppc_cpufreq_set_autonomous_perf - Configure performance bounds for
+ * autonomous mode
+ * @policy: cpufreq policy structure
+ *
+ * When enabling autonomous selection, program MIN_PERF and MAX_PERF from
+ * current policy limits so that the platform uses the correct performance
+ * bounds immediately.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
+ u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
+ int ret;
+
+ cppc_cpufreq_update_perf_limits(cpu_data, policy);
+
+ ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ if (ret) {
+ cpu_data->perf_ctrls.min_perf = old_min_perf;
+ cpu_data->perf_ctrls.max_perf = old_max_perf;
+ return ret;
+ }
+
+ return 0;
+}
+
static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
@@ -885,20 +915,8 @@ static ssize_t store_auto_select(struct cpufreq_policy *policy,
cpu_data->perf_ctrls.auto_sel = val;
if (val) {
- u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
- u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
-
- /*
- * When enabling autonomous selection, program MIN_PERF and
- * MAX_PERF from current policy limits so that the platform
- * uses the correct performance bounds immediately.
- */
- cppc_cpufreq_update_perf_limits(cpu_data, policy);
-
- ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ ret = cppc_cpufreq_set_autonomous_perf(policy);
if (ret) {
- cpu_data->perf_ctrls.min_perf = old_min_perf;
- cpu_data->perf_ctrls.max_perf = old_max_perf;
cppc_set_auto_sel(policy->cpu, false);
cpu_data->perf_ctrls.auto_sel = false;
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes
2026-05-08 11:19 [PATCH v2 0/2] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
2026-05-08 11:19 ` [PATCH v2 1/2] cpufreq: cppc: Refactor autonomous perf limit programming Xueqin Luo
@ 2026-05-08 11:19 ` Xueqin Luo
2026-05-10 6:14 ` kernel test robot
1 sibling, 1 reply; 7+ messages in thread
From: Xueqin Luo @ 2026-05-08 11:19 UTC (permalink / raw)
To: rafael, viresh.kumar, zhanjie9, zhenglifeng1, pierre.gondois,
sumitg, linux-pm, linux-kernel
Cc: Xueqin Luo
ACPI CPPC specification requires OSPM to re-evaluate the Highest
Performance register when Notify(0x85) is received for a processor
device.
Implement cppc_cpufreq_update_limits() to refresh the cached
highest_perf capability through cppc_get_highest_perf() and update
policy->cpuinfo.max_freq accordingly.
When autonomous selection mode is enabled, reprogram the runtime
MIN_PERF/MAX_PERF envelope against the updated Highest Performance
capability through cppc_cpufreq_set_autonomous_perf().
Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
--
Changes in v2:
Please ignore the previous version.
Fix variable naming issue causing build failure
---
drivers/cpufreq/cppc_cpufreq.c | 45 ++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 7ddf4296c474..09c7f2ba0540 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -873,6 +873,50 @@ static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
return 0;
}
+static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ u32 prev_highest_perf;
+ u32 highest_perf;
+ int ret;
+
+ guard(cpufreq_policy_write)(policy);
+
+ prev_highest_perf = cpu_data->perf_caps.highest_perf;
+
+ ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
+ if (ret)
+ return;
+
+ if (highest_perf == prev_highest_perf)
+ return;
+
+ cpu_data->perf_caps.highest_perf = highest_perf;
+ if (cpu_data->perf_caps.nominal_perf > highest_perf)
+ cpu_data->perf_caps.nominal_perf = highest_perf;
+
+ policy->max = cppc_perf_to_khz(&cpu_data->perf_caps,
+ policy->boost_enabled ?
+ highest_perf :
+ cpu_data->perf_caps.nominal_perf);
+
+ policy->cpuinfo.max_freq = policy->max;
+
+ /*
+ * Autonomous selection mode uses MIN/MAX performance as runtime
+ * hardware control bounds.
+ *
+ * Re-program them when highest_perf changes.
+ */
+ if (cpu_data->perf_ctrls.auto_sel)
+ cppc_cpufreq_set_autonomous_perf(policy);
+
+ pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
+ policy->cpu,
+ prev_highest_perf,
+ highest_perf);
+}
+
static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
@@ -1027,6 +1071,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.init = cppc_cpufreq_cpu_init,
.exit = cppc_cpufreq_cpu_exit,
.set_boost = cppc_cpufreq_set_boost,
+ .update_limits = cppc_cpufreq_update_limits,
.attr = cppc_cpufreq_attr,
.name = "cppc_cpufreq",
};
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes
2026-05-08 11:19 ` [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
@ 2026-05-10 6:14 ` kernel test robot
2026-05-11 7:56 ` [PATCH v3] " Xueqin Luo
0 siblings, 1 reply; 7+ messages in thread
From: kernel test robot @ 2026-05-10 6:14 UTC (permalink / raw)
To: Xueqin Luo, rafael, viresh.kumar, zhanjie9, zhenglifeng1,
pierre.gondois, sumitg, linux-pm, linux-kernel
Cc: llvm, oe-kbuild-all, Xueqin Luo
Hi Xueqin,
kernel test robot noticed the following build errors:
[auto build test ERROR on rafael-pm/linux-next]
[also build test ERROR on rafael-pm/bleeding-edge linus/master v7.1-rc2 next-20260508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Xueqin-Luo/cpufreq-cppc-Add-update_limits-support-for-Highest-Performance-changes/20260510-093030
base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link: https://lore.kernel.org/r/20260508111932.185886-3-luoxueqin%40kylinos.cn
patch subject: [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes
config: riscv-randconfig-002-20260510 (https://download.01.org/0day-ci/archive/20260510/202605101404.fqz0MXIe-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 5bac06718f502014fade905512f1d26d578a18f3)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260510/202605101404.fqz0MXIe-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605101404.fqz0MXIe-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
>> drivers/cpufreq/cppc_cpufreq.c:857:43: error: incompatible pointer types passing 'u32 *' (aka 'unsigned int *') to parameter of type 'u64 *' (aka 'unsigned long long *') [-Wincompatible-pointer-types]
857 | ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
| ^~~~~~~~~~~~~
include/acpi/cppc_acpi.h:157:51: note: passing argument to parameter 'highest_perf' here
157 | extern int cppc_get_highest_perf(int cpunum, u64 *highest_perf);
| ^
>> drivers/cpufreq/cppc_cpufreq.c:882:3: error: call to undeclared function 'cppc_cpufreq_set_autonomous_perf'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
882 | cppc_cpufreq_set_autonomous_perf(policy);
| ^
>> drivers/cpufreq/cppc_cpufreq.c:886:4: warning: format specifies type 'unsigned long long' but the argument has type 'u32' (aka 'unsigned int') [-Wformat]
884 | pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
| ~~~~
| %u
885 | policy->cpu,
886 | prev_highest_perf,
| ^~~~~~~~~~~~~~~~~
include/linux/printk.h:641:38: note: expanded from macro 'pr_debug'
641 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:134:18: note: expanded from macro 'no_printk'
134 | _printk(fmt, ##__VA_ARGS__); \
| ~~~ ^~~~~~~~~~~
drivers/cpufreq/cppc_cpufreq.c:887:4: warning: format specifies type 'unsigned long long' but the argument has type 'u32' (aka 'unsigned int') [-Wformat]
884 | pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
| ~~~~
| %u
885 | policy->cpu,
886 | prev_highest_perf,
887 | highest_perf);
| ^~~~~~~~~~~~
include/linux/printk.h:641:38: note: expanded from macro 'pr_debug'
641 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:134:18: note: expanded from macro 'no_printk'
134 | _printk(fmt, ##__VA_ARGS__); \
| ~~~ ^~~~~~~~~~~
2 warnings and 2 errors generated.
vim +857 drivers/cpufreq/cppc_cpufreq.c
845
846 static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
847 {
848 struct cppc_cpudata *cpu_data = policy->driver_data;
849 u32 prev_highest_perf;
850 u32 highest_perf;
851 int ret;
852
853 guard(cpufreq_policy_write)(policy);
854
855 prev_highest_perf = cpu_data->perf_caps.highest_perf;
856
> 857 ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
858 if (ret)
859 return;
860
861 if (highest_perf == prev_highest_perf)
862 return;
863
864 cpu_data->perf_caps.highest_perf = highest_perf;
865 if (cpu_data->perf_caps.nominal_perf > highest_perf)
866 cpu_data->perf_caps.nominal_perf = highest_perf;
867
868 policy->max = cppc_perf_to_khz(&cpu_data->perf_caps,
869 policy->boost_enabled ?
870 highest_perf :
871 cpu_data->perf_caps.nominal_perf);
872
873 policy->cpuinfo.max_freq = policy->max;
874
875 /*
876 * Autonomous selection mode uses MIN/MAX performance as runtime
877 * hardware control bounds.
878 *
879 * Re-program them when highest_perf changes.
880 */
881 if (cpu_data->perf_ctrls.auto_sel)
> 882 cppc_cpufreq_set_autonomous_perf(policy);
883
884 pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
885 policy->cpu,
> 886 prev_highest_perf,
887 highest_perf);
888 }
889
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3] cpufreq: cppc: Add update_limits support for Highest Performance changes
2026-05-10 6:14 ` kernel test robot
@ 2026-05-11 7:56 ` Xueqin Luo
2026-05-11 16:16 ` Pierre Gondois
0 siblings, 1 reply; 7+ messages in thread
From: Xueqin Luo @ 2026-05-11 7:56 UTC (permalink / raw)
To: lkp
Cc: linux-kernel, linux-pm, llvm, luoxueqin, oe-kbuild-all,
pierre.gondois, rafael, sumitg, viresh.kumar, zhanjie9,
zhenglifeng1
ACPI CPPC specification requires OSPM to re-evaluate the Highest
Performance register when Notify(0x85) is received for a processor
device.
Implement cppc_cpufreq_update_limits() to refresh the cached
highest_perf capability through cppc_get_highest_perf() and update
policy->cpuinfo.max_freq accordingly.
When autonomous selection mode is enabled, reprogram the runtime
MIN_PERF/MAX_PERF envelope against the updated Highest Performance
capability through cppc_cpufreq_set_autonomous_perf().
--
change v2->v3:
- Fix build issues reported by kernel test robot
- Fold cppc_cpufreq_set_autonomous_perf() refactoring into
this patch to keep it self-contained
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605101404.fqz0MXIe-lkp@intel.com/
Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
---
drivers/cpufreq/cppc_cpufreq.c | 89 +++++++++++++++++++++++++++++-----
1 file changed, 76 insertions(+), 13 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 7e7f9dfb7a24..9184d5570de8 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -843,6 +843,80 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
return 0;
}
+/**
+ * cppc_cpufreq_set_autonomous_perf - Configure performance bounds for
+ * autonomous mode
+ * @policy: cpufreq policy structure
+ *
+ * When enabling autonomous selection, program MIN_PERF and MAX_PERF from
+ * current policy limits so that the platform uses the correct performance
+ * bounds immediately.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
+ u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
+ int ret;
+
+ cppc_cpufreq_update_perf_limits(cpu_data, policy);
+
+ ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ if (ret) {
+ cpu_data->perf_ctrls.min_perf = old_min_perf;
+ cpu_data->perf_ctrls.max_perf = old_max_perf;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ u64 prev_highest_perf;
+ u64 highest_perf;
+ u64 nominal_perf;
+ int ret;
+
+ guard(cpufreq_policy_write)(policy);
+
+ prev_highest_perf = cpu_data->perf_caps.highest_perf;
+
+ ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
+ if (ret)
+ return;
+
+ if (highest_perf == prev_highest_perf)
+ return;
+
+ cpu_data->perf_caps.highest_perf = highest_perf;
+ nominal_perf = min_t(u64, highest_perf,
+ cpu_data->perf_caps.nominal_perf);
+
+ policy->max = cppc_perf_to_khz(&cpu_data->perf_caps,
+ policy->boost_enabled ?
+ highest_perf : nominal_perf);
+
+ policy->cpuinfo.max_freq = policy->max;
+
+ /*
+ * Autonomous selection mode uses MIN/MAX performance as runtime
+ * hardware control bounds.
+ *
+ * Re-program them when highest_perf changes.
+ */
+ if (cpu_data->perf_ctrls.auto_sel)
+ cppc_cpufreq_set_autonomous_perf(policy);
+
+ pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
+ policy->cpu,
+ prev_highest_perf,
+ highest_perf);
+}
+
static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
@@ -885,20 +959,8 @@ static ssize_t store_auto_select(struct cpufreq_policy *policy,
cpu_data->perf_ctrls.auto_sel = val;
if (val) {
- u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
- u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
-
- /*
- * When enabling autonomous selection, program MIN_PERF and
- * MAX_PERF from current policy limits so that the platform
- * uses the correct performance bounds immediately.
- */
- cppc_cpufreq_update_perf_limits(cpu_data, policy);
-
- ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ ret = cppc_cpufreq_set_autonomous_perf(policy);
if (ret) {
- cpu_data->perf_ctrls.min_perf = old_min_perf;
- cpu_data->perf_ctrls.max_perf = old_max_perf;
cppc_set_auto_sel(policy->cpu, false);
cpu_data->perf_ctrls.auto_sel = false;
return ret;
@@ -1009,6 +1071,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.init = cppc_cpufreq_cpu_init,
.exit = cppc_cpufreq_cpu_exit,
.set_boost = cppc_cpufreq_set_boost,
+ .update_limits = cppc_cpufreq_update_limits,
.attr = cppc_cpufreq_attr,
.name = "cppc_cpufreq",
};
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3] cpufreq: cppc: Add update_limits support for Highest Performance changes
2026-05-11 7:56 ` [PATCH v3] " Xueqin Luo
@ 2026-05-11 16:16 ` Pierre Gondois
2026-05-11 16:43 ` Rafael J. Wysocki
0 siblings, 1 reply; 7+ messages in thread
From: Pierre Gondois @ 2026-05-11 16:16 UTC (permalink / raw)
To: Xueqin Luo, lkp
Cc: linux-kernel, linux-pm, llvm, oe-kbuild-all, rafael, sumitg,
viresh.kumar, zhanjie9, zhenglifeng1
Hello Xueqin,
On 5/11/26 09:56, Xueqin Luo wrote:
> ACPI CPPC specification requires OSPM to re-evaluate the Highest
> Performance register when Notify(0x85) is received for a processor
> device.
>
> Implement cppc_cpufreq_update_limits() to refresh the cached
> highest_perf capability through cppc_get_highest_perf() and update
> policy->cpuinfo.max_freq accordingly.
>
> When autonomous selection mode is enabled, reprogram the runtime
> MIN_PERF/MAX_PERF envelope against the updated Highest Performance
> capability through cppc_cpufreq_set_autonomous_perf().
>
> --
> change v2->v3:
> - Fix build issues reported by kernel test robot
> - Fold cppc_cpufreq_set_autonomous_perf() refactoring into
> this patch to keep it self-contained
>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202605101404.fqz0MXIe-lkp@intel.com/
> Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
> ---
> drivers/cpufreq/cppc_cpufreq.c | 89 +++++++++++++++++++++++++++++-----
> 1 file changed, 76 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 7e7f9dfb7a24..9184d5570de8 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -843,6 +843,80 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
> return 0;
> }
>
> +/**
> + * cppc_cpufreq_set_autonomous_perf - Configure performance bounds for
> + * autonomous mode
> + * @policy: cpufreq policy structure
> + *
> + * When enabling autonomous selection, program MIN_PERF and MAX_PERF from
> + * current policy limits so that the platform uses the correct performance
> + * bounds immediately.
> + *
> + * Return: 0 on success, negative error code on failure.
> + */
> +static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
> +{
> + struct cppc_cpudata *cpu_data = policy->driver_data;
> + u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
> + u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
> + int ret;
> +
> + cppc_cpufreq_update_perf_limits(cpu_data, policy);
> +
> + ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
> + if (ret) {
> + cpu_data->perf_ctrls.min_perf = old_min_perf;
> + cpu_data->perf_ctrls.max_perf = old_max_perf;
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
> +{
> + struct cppc_cpudata *cpu_data = policy->driver_data;
> + u64 prev_highest_perf;
> + u64 highest_perf;
> + u64 nominal_perf;
> + int ret;
> +
> + guard(cpufreq_policy_write)(policy);
> +
> + prev_highest_perf = cpu_data->perf_caps.highest_perf;
> +
> + ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
> + if (ret)
> + return;
> +
> + if (highest_perf == prev_highest_perf)
> + return;
> +
> + cpu_data->perf_caps.highest_perf = highest_perf;
> + nominal_perf = min_t(u64, highest_perf,
> + cpu_data->perf_caps.nominal_perf);
> +
I sent a patch to try to remove setting policy->max in drivers
in cpufreq drivers in general [1]. IMO policy->max should be
updated through a callback handler, maybe:
refresh_frequency_limits()
\-cpufreq_set_policy()
[1] https://lore.kernel.org/all/20260511135538.522653-4-pierre.gondois@arm.com/
> + policy->max = cppc_perf_to_khz(&cpu_data->perf_caps,
> + policy->boost_enabled ?
> + highest_perf : nominal_perf);
> +
There might be other things to check:
- Is the new highest_perf higher/equal than nominal_perf ?
Depending on the answer the boost capabilities/status will have to
be updated.
- IIUC it will be possible to update the nominal_perf in the next spec,
so this makes things a bit more complicated aswell.
https://lore.kernel.org/all/20260430142430.755437-3-sumitg@nvidia.com/
- Do we need to rebuild the whole topology ? Cf. highest_perf
is used as the CPU capacity in topology_init_cpu_capacity_cppc().
(maybe off topic)
- What is the relation between highest_perf and the (not yet introduced [1])
highest_freq value ? Since the highest_perf can evolve over time there
is no clear correlation between them IIUC.
https://mantis.uefi.org/mantis/view.php?id=2570
Some of the questions are more spec. related,
but this patch might be the right place to discuss them.
> + policy->cpuinfo.max_freq = policy->max;
> +
> + /*
> + * Autonomous selection mode uses MIN/MAX performance as runtime
> + * hardware control bounds.
> + *
> + * Re-program them when highest_perf changes.
> + */
> + if (cpu_data->perf_ctrls.auto_sel)
> + cppc_cpufreq_set_autonomous_perf(policy);
> +
> + pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
> + policy->cpu,
> + prev_highest_perf,
> + highest_perf);
> +}
> +
> static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
> {
> struct cppc_cpudata *cpu_data = policy->driver_data;
> @@ -885,20 +959,8 @@ static ssize_t store_auto_select(struct cpufreq_policy *policy,
> cpu_data->perf_ctrls.auto_sel = val;
>
> if (val) {
> - u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
> - u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
> -
> - /*
> - * When enabling autonomous selection, program MIN_PERF and
> - * MAX_PERF from current policy limits so that the platform
> - * uses the correct performance bounds immediately.
> - */
> - cppc_cpufreq_update_perf_limits(cpu_data, policy);
> -
> - ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
> + ret = cppc_cpufreq_set_autonomous_perf(policy);
> if (ret) {
> - cpu_data->perf_ctrls.min_perf = old_min_perf;
> - cpu_data->perf_ctrls.max_perf = old_max_perf;
> cppc_set_auto_sel(policy->cpu, false);
> cpu_data->perf_ctrls.auto_sel = false;
> return ret;
> @@ -1009,6 +1071,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
> .init = cppc_cpufreq_cpu_init,
> .exit = cppc_cpufreq_cpu_exit,
> .set_boost = cppc_cpufreq_set_boost,
> + .update_limits = cppc_cpufreq_update_limits,
> .attr = cppc_cpufreq_attr,
> .name = "cppc_cpufreq",
> };
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3] cpufreq: cppc: Add update_limits support for Highest Performance changes
2026-05-11 16:16 ` Pierre Gondois
@ 2026-05-11 16:43 ` Rafael J. Wysocki
0 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-05-11 16:43 UTC (permalink / raw)
To: Pierre Gondois
Cc: Xueqin Luo, lkp, linux-kernel, linux-pm, llvm, oe-kbuild-all,
rafael, sumitg, viresh.kumar, zhanjie9, zhenglifeng1
On Mon, May 11, 2026 at 6:17 PM Pierre Gondois <pierre.gondois@arm.com> wrote:
>
> Hello Xueqin,
>
> On 5/11/26 09:56, Xueqin Luo wrote:
> > ACPI CPPC specification requires OSPM to re-evaluate the Highest
> > Performance register when Notify(0x85) is received for a processor
> > device.
> >
> > Implement cppc_cpufreq_update_limits() to refresh the cached
> > highest_perf capability through cppc_get_highest_perf() and update
> > policy->cpuinfo.max_freq accordingly.
> >
> > When autonomous selection mode is enabled, reprogram the runtime
> > MIN_PERF/MAX_PERF envelope against the updated Highest Performance
> > capability through cppc_cpufreq_set_autonomous_perf().
> >
> > --
> > change v2->v3:
> > - Fix build issues reported by kernel test robot
> > - Fold cppc_cpufreq_set_autonomous_perf() refactoring into
> > this patch to keep it self-contained
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202605101404.fqz0MXIe-lkp@intel.com/
> > Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
> > ---
> > drivers/cpufreq/cppc_cpufreq.c | 89 +++++++++++++++++++++++++++++-----
> > 1 file changed, 76 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> > index 7e7f9dfb7a24..9184d5570de8 100644
> > --- a/drivers/cpufreq/cppc_cpufreq.c
> > +++ b/drivers/cpufreq/cppc_cpufreq.c
> > @@ -843,6 +843,80 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
> > return 0;
> > }
> >
> > +/**
> > + * cppc_cpufreq_set_autonomous_perf - Configure performance bounds for
> > + * autonomous mode
> > + * @policy: cpufreq policy structure
> > + *
> > + * When enabling autonomous selection, program MIN_PERF and MAX_PERF from
> > + * current policy limits so that the platform uses the correct performance
> > + * bounds immediately.
> > + *
> > + * Return: 0 on success, negative error code on failure.
> > + */
> > +static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
> > +{
> > + struct cppc_cpudata *cpu_data = policy->driver_data;
> > + u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
> > + u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
> > + int ret;
> > +
> > + cppc_cpufreq_update_perf_limits(cpu_data, policy);
> > +
> > + ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
> > + if (ret) {
> > + cpu_data->perf_ctrls.min_perf = old_min_perf;
> > + cpu_data->perf_ctrls.max_perf = old_max_perf;
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
> > +{
> > + struct cppc_cpudata *cpu_data = policy->driver_data;
> > + u64 prev_highest_perf;
> > + u64 highest_perf;
> > + u64 nominal_perf;
> > + int ret;
> > +
> > + guard(cpufreq_policy_write)(policy);
> > +
> > + prev_highest_perf = cpu_data->perf_caps.highest_perf;
> > +
> > + ret = cppc_get_highest_perf(policy->cpu, &highest_perf);
> > + if (ret)
> > + return;
> > +
> > + if (highest_perf == prev_highest_perf)
> > + return;
> > +
> > + cpu_data->perf_caps.highest_perf = highest_perf;
> > + nominal_perf = min_t(u64, highest_perf,
> > + cpu_data->perf_caps.nominal_perf);
> > +
>
> I sent a patch to try to remove setting policy->max in drivers
> in cpufreq drivers in general [1]. IMO policy->max should be
> updated through a callback handler, maybe:
>
> refresh_frequency_limits()
> \-cpufreq_set_policy()
>
> [1] https://lore.kernel.org/all/20260511135538.522653-4-pierre.gondois@arm.com/
Yes, that's the right thing to do it.
> > + policy->max = cppc_perf_to_khz(&cpu_data->perf_caps,
> > + policy->boost_enabled ?
> > + highest_perf : nominal_perf);
> > +
> There might be other things to check:
>
> - Is the new highest_perf higher/equal than nominal_perf ?
> Depending on the answer the boost capabilities/status will have to
> be updated.
>
> - IIUC it will be possible to update the nominal_perf in the next spec,
> so this makes things a bit more complicated aswell.
> https://lore.kernel.org/all/20260430142430.755437-3-sumitg@nvidia.com/
If you are referring to this one:
https://uefi.org/specs/ACPI/6.6/08_Processor_Configuration_and_Control.html#ospm-nominal-performance-register
it is about something somewhat different IIUC.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-11 16:43 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-08 11:19 [PATCH v2 0/2] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
2026-05-08 11:19 ` [PATCH v2 1/2] cpufreq: cppc: Refactor autonomous perf limit programming Xueqin Luo
2026-05-08 11:19 ` [PATCH] cpufreq: cppc: Add update_limits support for Highest Performance changes Xueqin Luo
2026-05-10 6:14 ` kernel test robot
2026-05-11 7:56 ` [PATCH v3] " Xueqin Luo
2026-05-11 16:16 ` Pierre Gondois
2026-05-11 16:43 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox