* [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups
@ 2026-06-19 17:31 Rafael J. Wysocki
2026-06-19 17:32 ` [PATCH v2 1/6] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:31 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
Hi,
This is in v2 because technically it is an update of
https://lore.kernel.org/linux-pm/2381464.iZASKD2KPV@rafael.j.wysocki/
but it contains new patches.
This series updates the intel_pstate driver to set cpuinfo_min_freq to a lower
value when HWP is enabled to support systems in which CPUs can actually run
at performance levels below the current minimum level.
It also carries out some code cleanups, mostly related to HWP, either in
preparation for the functional changes or top of them.
Thanks!
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/6] cpufreq: intel_pstate: Fix setting minimum P-state at init time
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
@ 2026-06-19 17:32 ` Rafael J. Wysocki
2026-06-19 17:35 ` [PATCH v2 2/6] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits() Rafael J. Wysocki
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:32 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
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>
---
v1 -> v2: No changes
---
drivers/cpufreq/intel_pstate.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2352,8 +2352,6 @@ static void intel_pstate_get_cpu_pstates
if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu);
-
- intel_pstate_set_min_pstate(cpu);
}
/*
@@ -3059,6 +3057,7 @@ static int __intel_pstate_cpu_init(struc
static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
{
int ret = __intel_pstate_cpu_init(policy);
+ struct cpudata *cpu;
if (ret)
return ret;
@@ -3069,11 +3068,11 @@ static int intel_pstate_cpu_init(struct
*/
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;
}
@@ -3304,8 +3303,6 @@ static int intel_cpufreq_cpu_init(struct
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) {
@@ -3326,9 +3323,15 @@ static int intel_cpufreq_cpu_init(struct
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);
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/6] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits()
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
2026-06-19 17:32 ` [PATCH v2 1/6] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
@ 2026-06-19 17:35 ` Rafael J. Wysocki
2026-06-19 17:40 ` [PATCH v2 3/6] cpufreq: intel_pstate: Set initial scaling_min_freq value Rafael J. Wysocki
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:35 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
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>
---
v1 -> v2: New patch
---
drivers/cpufreq/intel_pstate.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -587,11 +587,6 @@ static void intel_pstate_hybrid_hwp_adju
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);
@@ -1181,6 +1176,22 @@ static bool hybrid_clear_max_perf_cpu(vo
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;
@@ -1193,20 +1204,8 @@ static void __intel_pstate_get_hwp_cap(s
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)
@@ -2327,6 +2326,7 @@ static void intel_pstate_get_cpu_pstates
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;
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 3/6] cpufreq: intel_pstate: Set initial scaling_min_freq value
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
2026-06-19 17:32 ` [PATCH v2 1/6] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
2026-06-19 17:35 ` [PATCH v2 2/6] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits() Rafael J. Wysocki
@ 2026-06-19 17:40 ` Rafael J. Wysocki
2026-06-19 17:42 ` [PATCH v2 4/6] cpufreq: intel_pstate: Consolidate frequency values computation Rafael J. Wysocki
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:40 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Currently, intel_pstate sets cpuinfo_min_freq to the minimum P-state
value retrieved from MSR_PLATFORM_INFO (bits 40:47) which prevents users
from setting scaling_min_freq below it. However, there are systems
where CPUs may actually run at P-states below that limit and the power
of the processor is then lower than when they run at the limit P-state,
even though running them at the limit P-state may still be more
energy-efficient.
To allow users to utilize the low P-states in question, notice that when
HWP is enabled, the LOWEST_PERF value from MSR_HWP_CAPABILITIES can be
used for setting cpuinfo_min_freq instead of the minimum P-state value
mentioned above, but in order to preserve the default behavior, use the
observation that after commit 8c83947c5dbb ("cpufreq: Use policy->min/max
init as QoS request"), cpufreq drivers can request the initial
scaling_min_freq values above cpuinfo_min_freq by setting policy->min to
those values in their .init() callbacks.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
v1 -> v2:
* Rely on intel_pstate_update_freq_limits() to update the cached frequency
values and modify it to take the min frequency into account (based on
Sashiko feedback:
https://sashiko.dev/#/patchset/2381464.iZASKD2KPV%40rafael.j.wysocki)
* Minor tweaks in the changelog
---
drivers/cpufreq/intel_pstate.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -589,14 +589,6 @@ static void intel_pstate_hybrid_hwp_adju
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);
}
static bool turbo_is_disabled(void)
@@ -1181,15 +1173,21 @@ static void intel_pstate_update_freq_lim
int scaling = cpu->pstate.scaling;
unsigned int turbo_freq = cpu->pstate.turbo_pstate * scaling;
unsigned int max_freq = cpu->pstate.max_pstate * scaling;
+ unsigned int min_freq = cpu->pstate.min_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);
+ if (min_freq > perf_ctl_scaling)
+ min_freq = rounddown(min_freq, perf_ctl_scaling);
+ else
+ min_freq = perf_ctl_scaling;
}
cpu->pstate.turbo_freq = turbo_freq;
cpu->pstate.max_freq = max_freq;
+ cpu->pstate.min_freq = min_freq;
}
static void __intel_pstate_get_hwp_cap(struct cpudata *cpu)
@@ -1198,6 +1196,7 @@ static void __intel_pstate_get_hwp_cap(s
rdmsrq_on_cpu(cpu->cpu, MSR_HWP_CAPABILITIES, &cap);
WRITE_ONCE(cpu->hwp_cap_cached, cap);
+ cpu->pstate.min_pstate = HWP_LOWEST_PERF(cap);
cpu->pstate.max_pstate = HWP_GUARANTEED_PERF(cap);
cpu->pstate.turbo_pstate = HWP_HIGHEST_PERF(cap);
}
@@ -2317,7 +2316,6 @@ static void intel_pstate_get_cpu_pstates
int perf_ctl_scaling = pstate_funcs.get_scaling();
cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(cpu->cpu);
- cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
if (hwp_active && !hwp_mode_bdw) {
@@ -2337,6 +2335,7 @@ static void intel_pstate_get_cpu_pstates
hybrid_update_capacity(cpu);
} else {
cpu->pstate.scaling = perf_ctl_scaling;
+ cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu);
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
}
@@ -3047,6 +3046,13 @@ static int __intel_pstate_cpu_init(struc
policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+ /*
+ * If policy->min is greater than policy->cpuinfo.min_freq, the cpufreq
+ * core will use this value for initializing scaling_min_freq.
+ */
+ if (hwp_active)
+ policy->min = pstate_funcs.get_min(cpu->cpu) * cpu->pstate.perf_ctl_scaling;
+
intel_pstate_init_acpi_perf_limits(policy);
policy->fast_switch_possible = true;
@@ -3313,6 +3319,7 @@ static int intel_cpufreq_cpu_init(struct
cpu = all_cpu_data[policy->cpu];
if (hwp_active) {
+ unsigned int hwp;
u64 value;
policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY_HWP;
@@ -3324,14 +3331,15 @@ static int intel_cpufreq_cpu_init(struct
cpu->epp_cached = intel_pstate_get_epp(cpu, value);
+ hwp = intel_pstate_freq_to_hwp(cpu, policy->min);
intel_cpufreq_hwp_update(cpu, cpu->pstate.min_pstate,
- cpu->pstate.max_pstate,
- cpu->pstate.min_pstate, false);
+ cpu->pstate.max_pstate, hwp, false);
+ policy->cur = policy->min;
} else {
policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY;
intel_pstate_set_min_pstate(cpu);
+ policy->cur = policy->cpuinfo.min_freq;
}
- policy->cur = policy->cpuinfo.min_freq;
freq = DIV_ROUND_UP(cpu->pstate.turbo_freq * global.min_perf_pct, 100);
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 4/6] cpufreq: intel_pstate: Consolidate frequency values computation
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
` (2 preceding siblings ...)
2026-06-19 17:40 ` [PATCH v2 3/6] cpufreq: intel_pstate: Set initial scaling_min_freq value Rafael J. Wysocki
@ 2026-06-19 17:42 ` Rafael J. Wysocki
2026-06-19 17:44 ` [PATCH v2 5/6] cpufreq: intel_pstate: Consolidate HWP P-states initialization Rafael J. Wysocki
2026-06-19 17:45 ` [PATCH v2 6/6] cpufreq: intel_pstate: Move two functions closer to callers Rafael J. Wysocki
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:42 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
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>
---
v1 -> v2: New patch
---
drivers/cpufreq/intel_pstate.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2324,7 +2324,6 @@ static void intel_pstate_get_cpu_pstates
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;
}
@@ -2340,11 +2339,7 @@ static void intel_pstate_get_cpu_pstates
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();
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 5/6] cpufreq: intel_pstate: Consolidate HWP P-states initialization
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
` (3 preceding siblings ...)
2026-06-19 17:42 ` [PATCH v2 4/6] cpufreq: intel_pstate: Consolidate frequency values computation Rafael J. Wysocki
@ 2026-06-19 17:44 ` Rafael J. Wysocki
2026-06-19 17:45 ` [PATCH v2 6/6] cpufreq: intel_pstate: Move two functions closer to callers Rafael J. Wysocki
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:44 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
After previous changes, intel_pstate_hybrid_hwp_adjust() does not do
much and its name and kerneldoc comment (which is not really necessary
becuase the function is static) have become a bit confusing. Moreover,
the initialization of P-states on systems with HWP enabled is divided
between it and a direct conditional statement branch in
intel_pstate_get_cpu_pstates() which is not super-easy to follow.
Address this by introducing intel_pstate_get_hwp_pstates() for the
entire HWP-specific initialization of P-states and moving the code from
intel_pstate_hybrid_hwp_adjust() into it along with some HWP-related
code from intel_pstate_get_cpu_pstates().
No intentional functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
v1 -> v2: New patch
---
drivers/cpufreq/intel_pstate.c | 103 +++++++++++++++++++----------------------
1 file changed, 50 insertions(+), 53 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -556,41 +556,6 @@ static int intel_pstate_freq_to_hwp(stru
return intel_pstate_freq_to_hwp_rel(cpu, freq, CPUFREQ_RELATION_L);
}
-/**
- * intel_pstate_hybrid_hwp_adjust - Calibrate HWP performance levels.
- * @cpu: Target CPU.
- *
- * On hybrid processors, HWP may expose more performance levels than there are
- * P-states accessible through the PERF_CTL interface. If that happens, the
- * scaling factor between HWP performance levels and CPU frequency will be less
- * than the scaling factor between P-state values and CPU frequency.
- *
- * In that case, adjust the CPU parameters used in computations accordingly.
- */
-static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
-{
- int perf_ctl_max_phys = cpu->pstate.max_pstate_physical;
- int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
- int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu);
- int scaling = cpu->pstate.scaling;
- int freq;
-
- pr_debug("CPU%d: PERF_CTL max_phys = %d\n", cpu->cpu, perf_ctl_max_phys);
- pr_debug("CPU%d: PERF_CTL turbo = %d\n", cpu->cpu, perf_ctl_turbo);
- pr_debug("CPU%d: PERF_CTL scaling = %d\n", cpu->cpu, perf_ctl_scaling);
- pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate);
- pr_debug("CPU%d: HWP_CAP highest = %d\n", cpu->cpu, cpu->pstate.turbo_pstate);
- pr_debug("CPU%d: HWP-to-frequency scaling factor: %d\n", cpu->cpu, scaling);
-
- if (scaling == perf_ctl_scaling)
- return;
-
- hwp_is_hybrid = true;
-
- freq = perf_ctl_max_phys * perf_ctl_scaling;
- cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq);
-}
-
static bool turbo_is_disabled(void)
{
u64 misc_en;
@@ -2311,32 +2276,64 @@ static void intel_pstate_set_min_pstate(
intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
}
-static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
+static void intel_pstate_get_hwp_pstates(struct cpudata *cpu)
{
- int perf_ctl_scaling = pstate_funcs.get_scaling();
+ int perf_ctl_max_phys = cpu->pstate.max_pstate_physical;
+ int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
+ int perf_ctl_turbo = cpu->pstate.turbo_pstate;
+ int cpuid = cpu->cpu;
+
+ __intel_pstate_get_hwp_cap(cpu);
+
+ if (!pstate_funcs.get_cpu_scaling)
+ return;
+ pr_debug("CPU%d: PERF_CTL max_phys = %d\n", cpuid, perf_ctl_max_phys);
+ pr_debug("CPU%d: PERF_CTL turbo = %d\n", cpuid, perf_ctl_turbo);
+ pr_debug("CPU%d: PERF_CTL scaling = %d\n", cpuid, perf_ctl_scaling);
+ pr_debug("CPU%d: HWP_CAP lowest = %d\n", cpuid, cpu->pstate.min_pstate);
+ pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpuid, cpu->pstate.max_pstate);
+ pr_debug("CPU%d: HWP_CAP highest = %d\n", cpuid, cpu->pstate.turbo_pstate);
+
+ cpu->pstate.scaling = pstate_funcs.get_cpu_scaling(cpuid);
+
+ pr_debug("CPU%d: HWP-to-frequency scaling = %d\n", cpuid, cpu->pstate.scaling);
+
+ /*
+ * On hybrid processors, HWP may expose more performance levels than
+ * there are P-states accessible through the PERF_CTL interface. If
+ * that happens, the scaling between HWP performance levels and CPU
+ * frequency will be less than the scaling between P-state values and
+ * CPU frequency. In that case, update the maximum physical non-turbo
+ * performance level accordingly.
+ */
+ if (cpu->pstate.scaling != perf_ctl_scaling) {
+ int freq = perf_ctl_max_phys * perf_ctl_scaling;
+ unsigned int hwp = intel_pstate_freq_to_hwp(cpu, freq);
+
+ cpu->pstate.max_pstate_physical = hwp;
+
+ hwp_is_hybrid = true;
+ }
+ /*
+ * If the CPU is going online for the first time and it was offline
+ * initially, asym capacity scaling needs to be updated.
+ */
+ hybrid_update_capacity(cpu);
+}
+
+static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
+{
cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(cpu->cpu);
- cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
+ cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
+ cpu->pstate.perf_ctl_scaling = pstate_funcs.get_scaling();
+ cpu->pstate.scaling = cpu->pstate.perf_ctl_scaling;
if (hwp_active && !hwp_mode_bdw) {
- __intel_pstate_get_hwp_cap(cpu);
-
- if (pstate_funcs.get_cpu_scaling) {
- cpu->pstate.scaling = pstate_funcs.get_cpu_scaling(cpu->cpu);
- intel_pstate_hybrid_hwp_adjust(cpu);
- } else {
- cpu->pstate.scaling = perf_ctl_scaling;
- }
- /*
- * If the CPU is going online for the first time and it was
- * offline initially, asym capacity scaling needs to be updated.
- */
- hybrid_update_capacity(cpu);
+ intel_pstate_get_hwp_pstates(cpu);
} else {
- cpu->pstate.scaling = perf_ctl_scaling;
cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu);
- cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
}
intel_pstate_update_freq_limits(cpu);
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 6/6] cpufreq: intel_pstate: Move two functions closer to callers
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
` (4 preceding siblings ...)
2026-06-19 17:44 ` [PATCH v2 5/6] cpufreq: intel_pstate: Consolidate HWP P-states initialization Rafael J. Wysocki
@ 2026-06-19 17:45 ` Rafael J. Wysocki
5 siblings, 0 replies; 7+ messages in thread
From: Rafael J. Wysocki @ 2026-06-19 17:45 UTC (permalink / raw)
To: Linux PM; +Cc: LKML, Srinivas Pandruvada
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 functional impact.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
v1 -> v2: New patch
---
drivers/cpufreq/intel_pstate.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -2258,24 +2258,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_hwp_pstates(struct cpudata *cpu)
{
int perf_ctl_max_phys = cpu->pstate.max_pstate_physical;
@@ -2869,6 +2851,19 @@ static void intel_pstate_update_perf_lim
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;
@@ -2956,6 +2951,11 @@ static int intel_pstate_verify_policy(st
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];
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-19 17:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-19 17:31 [PATCH v2 0/6] cpufreq: intel_pstate: Set cpuinfo_min_freq to a lower value with HWP enabled plus cleanups Rafael J. Wysocki
2026-06-19 17:32 ` [PATCH v2 1/6] cpufreq: intel_pstate: Fix setting minimum P-state at init time Rafael J. Wysocki
2026-06-19 17:35 ` [PATCH v2 2/6] cpufreq: intel_pstate: Introduce intel_pstate_update_freq_limits() Rafael J. Wysocki
2026-06-19 17:40 ` [PATCH v2 3/6] cpufreq: intel_pstate: Set initial scaling_min_freq value Rafael J. Wysocki
2026-06-19 17:42 ` [PATCH v2 4/6] cpufreq: intel_pstate: Consolidate frequency values computation Rafael J. Wysocki
2026-06-19 17:44 ` [PATCH v2 5/6] cpufreq: intel_pstate: Consolidate HWP P-states initialization Rafael J. Wysocki
2026-06-19 17:45 ` [PATCH v2 6/6] cpufreq: intel_pstate: Move two functions closer to callers 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