* [PATCH v3 1/4] cpufreq: intel_pstate: Fix setting minimum P-state at init time
2026-06-24 17:32 [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Rafael J. Wysocki
@ 2026-06-24 17:33 ` Rafael J. Wysocki
2026-06-24 17:34 ` [PATCH v3 2/4] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits() Rafael J. Wysocki
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2026-06-24 17:33 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada, Doug Smythies
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
If HWP is enabled, writes to MSR_IA32_PERF_CTL have no effect,
so intel_pstate_get_cpu_pstates() should not attempt to call
intel_pstate_set_min_pstate() to set the minimum P-state for the
given CPU in that case.
Accordingly, remove the intel_pstate_set_min_pstate()
call from intel_pstate_get_cpu_pstates() and make both
intel_pstate_cpu_init() and intel_cpufreq_cpu_init() call
that function in their non-HWP code paths.
The HWP code path in intel_pstate_cpu_init() does not need to update
the current P-state of the CPU directly at all because it is taken
care of the processor automatically, but the HWP code path of
intel_cpufreq_cpu_init() should update it in principle to
initialize the DESIRED_PERF field in MSR_HWP_REQUEST. For this
purpose, make it call intel_cpufreq_hwp_update() and pass
the minimum P-state limit to it as the current target value along
with the current minimum and maximum limits.
Fixes: f6ebbcf08f37 ("cpufreq: intel_pstate: Implement passive mode with HWP enabled")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/cpufreq/intel_pstate.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 1f093e346430..95e41e975c45 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2354,8 +2354,6 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu);
-
- intel_pstate_set_min_pstate(cpu);
}
/*
@@ -3062,6 +3060,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
{
int ret = __intel_pstate_cpu_init(policy);
+ struct cpudata *cpu;
if (ret)
return ret;
@@ -3072,11 +3071,11 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
*/
policy->policy = CPUFREQ_POLICY_POWERSAVE;
- if (hwp_active) {
- struct cpudata *cpu = all_cpu_data[policy->cpu];
-
+ cpu = all_cpu_data[policy->cpu];
+ if (hwp_active)
cpu->epp_cached = intel_pstate_get_epp(cpu, 0);
- }
+ else
+ intel_pstate_set_min_pstate(cpu);
return 0;
}
@@ -3300,8 +3299,6 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
return ret;
policy->cpuinfo.transition_latency = INTEL_CPUFREQ_TRANSITION_LATENCY;
- /* This reflects the intel_pstate_get_cpu_pstates() setting. */
- policy->cur = policy->cpuinfo.min_freq;
req = kzalloc_objs(*req, 2);
if (!req) {
@@ -3322,9 +3319,15 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
WRITE_ONCE(cpu->hwp_req_cached, value);
cpu->epp_cached = intel_pstate_get_epp(cpu, value);
+
+ intel_cpufreq_hwp_update(cpu, cpu->pstate.min_pstate,
+ cpu->pstate.max_pstate,
+ cpu->pstate.min_pstate, false);
} else {
policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY;
+ intel_pstate_set_min_pstate(cpu);
}
+ policy->cur = policy->cpuinfo.min_freq;
freq = DIV_ROUND_UP(cpu->pstate.turbo_freq * global.min_perf_pct, 100);
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/4] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits()
2026-06-24 17:32 [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Rafael J. Wysocki
2026-06-24 17:33 ` [PATCH v3 1/4] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
@ 2026-06-24 17:34 ` Rafael J. Wysocki
2026-06-24 17:35 ` [PATCH v3 3/4] cpufreq: intel_pstate: Consolidate frequency values computation Rafael J. Wysocki
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2026-06-24 17:34 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada, Doug Smythies
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Introduce a new helper function, intel_pstate_update_freq_limits(),
for updating the max and turbo frequency values for the given CPU after
updating the corresponding P-states.
Use it in intel_pstate_get_hwp_cap() and intel_pstate_get_cpu_pstates(),
in the latter case instead of the direct updates of the max and turbo
frequency values in intel_pstate_hybrid_hwp_adjust().
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/cpufreq/intel_pstate.c | 36 +++++++++++++++++-----------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 95e41e975c45..e143c80a3215 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -587,11 +587,6 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
hwp_is_hybrid = true;
- cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_pstate * scaling,
- perf_ctl_scaling);
- cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling,
- perf_ctl_scaling);
-
freq = perf_ctl_max_phys * perf_ctl_scaling;
cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq);
@@ -1183,6 +1178,22 @@ static bool hybrid_clear_max_perf_cpu(void)
return ret;
}
+static void intel_pstate_update_freq_limits(struct cpudata *cpu)
+{
+ int scaling = cpu->pstate.scaling;
+ unsigned int turbo_freq = cpu->pstate.turbo_pstate * scaling;
+ unsigned int max_freq = cpu->pstate.max_pstate * scaling;
+ int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
+
+ if (scaling != perf_ctl_scaling) {
+ turbo_freq = rounddown(turbo_freq, perf_ctl_scaling);
+ max_freq = rounddown(max_freq, perf_ctl_scaling);
+ }
+
+ cpu->pstate.turbo_freq = turbo_freq;
+ cpu->pstate.max_freq = max_freq;
+}
+
static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
{
u64 cap;
@@ -1195,20 +1206,8 @@ static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
static void intel_pstate_get_hwp_cap(struct cpudata *cpu)
{
- int scaling = cpu->pstate.scaling;
-
__intel_pstate_get_hwp_cap(cpu);
-
- cpu->pstate.max_freq = cpu->pstate.max_pstate * scaling;
- cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling;
- if (scaling != cpu->pstate.perf_ctl_scaling) {
- int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
-
- cpu->pstate.max_freq = rounddown(cpu->pstate.max_freq,
- perf_ctl_scaling);
- cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_freq,
- perf_ctl_scaling);
- }
+ intel_pstate_update_freq_limits(cpu);
}
static void hybrid_update_capacity(struct cpudata *cpu)
@@ -2329,6 +2328,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
if (pstate_funcs.get_cpu_scaling) {
cpu->pstate.scaling = pstate_funcs.get_cpu_scaling(cpu->cpu);
intel_pstate_hybrid_hwp_adjust(cpu);
+ intel_pstate_update_freq_limits(cpu);
} else {
cpu->pstate.scaling = perf_ctl_scaling;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 3/4] cpufreq: intel_pstate: Consolidate frequency values computation
2026-06-24 17:32 [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Rafael J. Wysocki
2026-06-24 17:33 ` [PATCH v3 1/4] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
2026-06-24 17:34 ` [PATCH v3 2/4] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits() Rafael J. Wysocki
@ 2026-06-24 17:35 ` Rafael J. Wysocki
2026-06-24 17:36 ` [PATCH v3 4/4] cpufreq: intel_pstate: Move two functions closer to callers Rafael J. Wysocki
2026-06-30 4:21 ` [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Doug Smythies
4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2026-06-24 17:35 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada, Doug Smythies
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Update intel_pstate_get_cpu_pstates() to use
intel_pstate_update_freq_limits() for computing the max and
turbo frequency values in all cases, including non-hybrid HWP
and HWP disabled.
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/cpufreq/intel_pstate.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index e143c80a3215..edc90ecb0b00 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -590,13 +590,11 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
freq = perf_ctl_max_phys * perf_ctl_scaling;
cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq);
- freq = cpu->pstate.min_pstate * perf_ctl_scaling;
- cpu->pstate.min_freq = freq;
/*
* Cast the min P-state value retrieved via pstate_funcs.get_min() to
* the effective range of HWP performance levels.
*/
- cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, freq);
+ cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, cpu->pstate.min_freq);
}
static bool turbo_is_disabled(void)
@@ -2320,6 +2318,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(cpu->cpu);
cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
+ cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling;
cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
if (hwp_active && !hwp_mode_bdw) {
@@ -2328,7 +2327,6 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
if (pstate_funcs.get_cpu_scaling) {
cpu->pstate.scaling = pstate_funcs.get_cpu_scaling(cpu->cpu);
intel_pstate_hybrid_hwp_adjust(cpu);
- intel_pstate_update_freq_limits(cpu);
} else {
cpu->pstate.scaling = perf_ctl_scaling;
}
@@ -2343,11 +2341,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
}
- if (cpu->pstate.scaling == perf_ctl_scaling) {
- cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling;
- cpu->pstate.max_freq = cpu->pstate.max_pstate * perf_ctl_scaling;
- cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * perf_ctl_scaling;
- }
+ intel_pstate_update_freq_limits(cpu);
if (pstate_funcs.get_aperf_mperf_shift)
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 4/4] cpufreq: intel_pstate: Move two functions closer to callers
2026-06-24 17:32 [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Rafael J. Wysocki
` (2 preceding siblings ...)
2026-06-24 17:35 ` [PATCH v3 3/4] cpufreq: intel_pstate: Consolidate frequency values computation Rafael J. Wysocki
@ 2026-06-24 17:36 ` Rafael J. Wysocki
2026-06-30 4:21 ` [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Doug Smythies
4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2026-06-24 17:36 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada, Doug Smythies
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Move intel_pstate_set_pstate() and intel_pstate_set_min_pstate() that
are not used on systems with HWP enabled, closer to their first
callers.
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/cpufreq/intel_pstate.c | 36 +++++++++++++++++-----------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index edc90ecb0b00..25ef2848eebf 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2294,24 +2294,6 @@ static int hwp_get_cpu_scaling(int cpu)
return intel_pstate_cppc_get_scaling(cpu);
}
-static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
-{
- trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
- cpu->pstate.current_pstate = pstate;
- /*
- * Generally, there is no guarantee that this code will always run on
- * the CPU being updated, so force the register update to run on the
- * right CPU.
- */
- wrmsrq_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL,
- pstate_funcs.get_val(cpu, pstate));
-}
-
-static void intel_pstate_set_min_pstate(struct cpudata *cpu)
-{
- intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
-}
-
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
{
int perf_ctl_scaling = pstate_funcs.get_scaling();
@@ -2874,6 +2856,19 @@ static void intel_pstate_update_perf_limits(struct cpudata *cpu,
cpu->min_perf_ratio);
}
+static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
+{
+ trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
+ cpu->pstate.current_pstate = pstate;
+ /*
+ * Generally, there is no guarantee that this code will always run on
+ * the CPU being updated, so force the register update to run on the
+ * right CPU.
+ */
+ wrmsrq_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL,
+ pstate_funcs.get_val(cpu, pstate));
+}
+
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
{
struct cpudata *cpu;
@@ -2961,6 +2956,11 @@ static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
return 0;
}
+static void intel_pstate_set_min_pstate(struct cpudata *cpu)
+{
+ intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
+}
+
static int intel_cpufreq_cpu_offline(struct cpufreq_policy *policy)
{
struct cpudata *cpu = all_cpu_data[policy->cpu];
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* RE: [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups
2026-06-24 17:32 [PATCH v3 0/4] cpufreq: intel_pstate: A fix and some cleanups Rafael J. Wysocki
` (3 preceding siblings ...)
2026-06-24 17:36 ` [PATCH v3 4/4] cpufreq: intel_pstate: Move two functions closer to callers Rafael J. Wysocki
@ 2026-06-30 4:21 ` Doug Smythies
4 siblings, 0 replies; 6+ messages in thread
From: Doug Smythies @ 2026-06-30 4:21 UTC (permalink / raw)
To: 'Rafael J. Wysocki'
Cc: 'LKML', 'Srinivas Pandruvada', Doug Smythies,
'Linux PM'
Hi Rafael,
On 2026.06.24 10:32 Rafael wrote:
> Hi,
>
> This replaces
>
> https://lore.kernel.org/linux-pm/6005456.DvuYhMxLoT@rafael.j.wysocki/
>
> and drops the most significant change in it which was making intel_pstate
> set cpuinfo_min_freq to a lower value with HWP enabled. That change
> went too far and needs to be reconsidered.
>
> The other changes in the series, and in particular the fix in the first
> patch, are useful and will facilitate further improvements, so here
> they go.
I tested this patch set a little. It seems okay.
... Doug
>
> This series is independent of
>
> https://lore.kernel.org/linux-pm/6286434.lOV4Wx5bFT@rafael.j.wysocki/
>
> and applies to Linux 7.1.
>
> Thanks!
^ permalink raw reply [flat|nested] 6+ messages in thread