* [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