Linux Power Management development
 help / color / mirror / Atom feed
* [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; 5+ 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] 5+ 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; 5+ 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] 5+ 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; 5+ 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] 5+ 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; 5+ 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] 5+ 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
  0 siblings, 0 replies; 5+ 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] 5+ messages in thread

end of thread, other threads:[~2026-05-11  7:57 UTC | newest]

Thread overview: 5+ 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox