* [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
@ 2026-11-03 11:21 Guo Chen
2026-11-05 13:23 ` Lukasz Luba
2026-11-06 15:15 ` Rafael J. Wysocki (Intel)
0 siblings, 2 replies; 11+ messages in thread
From: Guo Chen @ 2026-11-03 11:21 UTC (permalink / raw)
To: Rafael J . Wysocki, Viresh Kumar, Lukasz Luba, Pavel Machek,
Len Brown, Vincent Donnefort, Matthias Kaehlcke
Cc: Rafael J . Wysocki, linux-pm, linux-kernel, stable, xin.liu,
aiqun.yu, tengfei.fan, tingwei.zhang
em_compute_costs() ranks all the frequencies of the table, boost ones
included. A non-boost frequency can be marked inefficient only because
a faster boost frequency has a lower or equal cost, e.g.
3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
skipped by governors rounding down to efficient frequencies (e.g.
ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
the best selectable frequency. Several frequencies can be affected.
Exclude the boost frequencies from the ranking in em_compute_costs() and
keep them all efficient, using the highest non-boost frequency of the
CPUFreq table, returned by the new helper
cpufreq_table_max_nonboost_freq(), as the boundary.
Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
---
Changes in v2:
- Drop prev_boost and keep all boost states efficient by resetting
prev_cost for them, as suggested by Lukasz. Boost states are no
longer ranked against each other.
- Retitle the patch to match the new behaviour (was "Rank boost and
non-boost frequencies separately") and reword the commit message.
Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-separately-v1-1-238a6b2bb888@oss.qualcomm.com/
---
include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
kernel/power/energy_model.c | 16 ++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index d3d0d9d02aa4..c93316141a11 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
return -EINVAL;
}
+static inline unsigned int
+cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
+{
+ struct cpufreq_frequency_table *pos;
+ unsigned int max = 0;
+
+ if (!policy->freq_table)
+ return 0;
+
+ /* The table may be unsorted, scan all of it for the highest one. */
+ cpufreq_for_each_valid_entry(pos, policy->freq_table) {
+ if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos->frequency > max)
+ max = pos->frequency;
+ }
+
+ return max;
+}
+
static inline int parse_perf_domain(int cpu, const char *list_name,
const char *cell_name,
struct of_phandle_args *args)
@@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
return -EINVAL;
}
+static inline unsigned int
+cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+
static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_name,
const char *cell_name, struct cpumask *cpumask,
struct of_phandle_args *pargs)
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index d19a65461ae8..5b1d095fd376 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
unsigned long flags)
{
unsigned long prev_cost = ULONG_MAX;
+ struct cpufreq_policy *policy;
+ unsigned int max_nonboost = 0;
int i, ret;
/* This is needed only for CPUs and EAS skip other devices */
if (!_is_cpu_device(dev))
return 0;
+ policy = cpufreq_cpu_get(dev->id);
+ if (policy) {
+ max_nonboost = cpufreq_table_max_nonboost_freq(policy);
+ cpufreq_cpu_put(policy);
+ }
+
/* Compute the cost of each performance state. */
for (i = nr_states - 1; i >= 0; i--) {
unsigned long power_res, cost;
+ bool boost = max_nonboost && table[i].frequency > max_nonboost;
if ((flags & EM_PERF_DOMAIN_ARTIFICIAL) && cb->get_cost) {
ret = cb->get_cost(dev, table[i].frequency, &cost);
@@ -284,6 +293,13 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
table[i].flags = EM_PERF_STATE_INEFFICIENT;
dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
table[i].frequency);
+ } else if (boost) {
+ /*
+ * Keep all boost states efficient. Resetting prev_cost
+ * also keeps the highest non-boost state efficient,
+ * then rank the rest on their own.
+ */
+ prev_cost = ULONG_MAX;
} else {
prev_cost = table[i].cost;
}
---
base-commit: f1ac44c32cba88ad65dcecd4a279661d14e93651
base-tree: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
change-id: 20261029-em-rank-boost-separately-a7e7c7d78058
Best regards,
--
Guo Chen <guo.chen@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-03 11:21 [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking Guo Chen
@ 2026-11-05 13:23 ` Lukasz Luba
2026-11-06 15:15 ` Rafael J. Wysocki (Intel)
1 sibling, 0 replies; 11+ messages in thread
From: Lukasz Luba @ 2026-11-05 13:23 UTC (permalink / raw)
To: Guo Chen
Cc: Len Brown, Pavel Machek, Rafael J . Wysocki, linux-pm,
Viresh Kumar, Matthias Kaehlcke, linux-kernel, stable, xin.liu,
aiqun.yu, tengfei.fan, tingwei.zhang, Rafael J . Wysocki
On 11/3/26 11:21, Guo Chen wrote:
> em_compute_costs() ranks all the frequencies of the table, boost ones
> included. A non-boost frequency can be marked inefficient only because
> a faster boost frequency has a lower or equal cost, e.g.
>
> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>
> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
> skipped by governors rounding down to efficient frequencies (e.g.
> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
> the best selectable frequency. Several frequencies can be affected.
>
> Exclude the boost frequencies from the ranking in em_compute_costs() and
> keep them all efficient, using the highest non-boost frequency of the
> CPUFreq table, returned by the new helper
> cpufreq_table_max_nonboost_freq(), as the boundary.
>
> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
> ---
> Changes in v2:
> - Drop prev_boost and keep all boost states efficient by resetting
> prev_cost for them, as suggested by Lukasz. Boost states are no
> longer ranked against each other.
> - Retitle the patch to match the new behaviour (was "Rank boost and
> non-boost frequencies separately") and reword the commit message.
>
> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-separately-v1-1-238a6b2bb888@oss.qualcomm.com/
> ---
> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
> kernel/power/energy_model.c | 16 ++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index d3d0d9d02aa4..c93316141a11 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
> return -EINVAL;
> }
>
> +static inline unsigned int
> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> +{
> + struct cpufreq_frequency_table *pos;
> + unsigned int max = 0;
> +
> + if (!policy->freq_table)
> + return 0;
> +
> + /* The table may be unsorted, scan all of it for the highest one. */
> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos->frequency > max)
> + max = pos->frequency;
> + }
> +
> + return max;
> +}
> +
> static inline int parse_perf_domain(int cpu, const char *list_name,
> const char *cell_name,
> struct of_phandle_args *args)
> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
> return -EINVAL;
> }
>
> +static inline unsigned int
> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> +{
> + return 0;
> +}
> +
> static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_name,
> const char *cell_name, struct cpumask *cpumask,
> struct of_phandle_args *pargs)
> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
> index d19a65461ae8..5b1d095fd376 100644
> --- a/kernel/power/energy_model.c
> +++ b/kernel/power/energy_model.c
> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
> unsigned long flags)
> {
> unsigned long prev_cost = ULONG_MAX;
> + struct cpufreq_policy *policy;
> + unsigned int max_nonboost = 0;
> int i, ret;
>
> /* This is needed only for CPUs and EAS skip other devices */
> if (!_is_cpu_device(dev))
> return 0;
>
> + policy = cpufreq_cpu_get(dev->id);
> + if (policy) {
> + max_nonboost = cpufreq_table_max_nonboost_freq(policy);
> + cpufreq_cpu_put(policy);
> + }
> +
> /* Compute the cost of each performance state. */
> for (i = nr_states - 1; i >= 0; i--) {
> unsigned long power_res, cost;
> + bool boost = max_nonboost && table[i].frequency > max_nonboost;
>
> if ((flags & EM_PERF_DOMAIN_ARTIFICIAL) && cb->get_cost) {
> ret = cb->get_cost(dev, table[i].frequency, &cost);
> @@ -284,6 +293,13 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
> table[i].flags = EM_PERF_STATE_INEFFICIENT;
> dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
> table[i].frequency);
> + } else if (boost) {
> + /*
> + * Keep all boost states efficient. Resetting prev_cost
> + * also keeps the highest non-boost state efficient,
> + * then rank the rest on their own.
> + */
> + prev_cost = ULONG_MAX;
> } else {
> prev_cost = table[i].cost;
> }
>
> ---
> base-commit: f1ac44c32cba88ad65dcecd4a279661d14e93651
> base-tree: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> change-id: 20261029-em-rank-boost-separately-a7e7c7d78058
>
> Best regards,
> --
> Guo Chen <guo.chen@oss.qualcomm.com>
LGTM,
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-03 11:21 [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking Guo Chen
2026-11-05 13:23 ` Lukasz Luba
@ 2026-11-06 15:15 ` Rafael J. Wysocki (Intel)
2026-11-09 6:47 ` Guo Chen
1 sibling, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-11-06 15:15 UTC (permalink / raw)
To: Guo Chen
Cc: Rafael J . Wysocki, Viresh Kumar, Lukasz Luba, Pavel Machek,
Len Brown, Vincent Donnefort, Matthias Kaehlcke,
Rafael J . Wysocki, linux-pm, linux-kernel, stable, xin.liu,
aiqun.yu, tengfei.fan, tingwei.zhang
On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com> wrote:
>
> em_compute_costs() ranks all the frequencies of the table, boost ones
> included. A non-boost frequency can be marked inefficient only because
> a faster boost frequency has a lower or equal cost, e.g.
>
> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>
> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
> skipped by governors rounding down to efficient frequencies (e.g.
> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
> the best selectable frequency. Several frequencies can be affected.
>
> Exclude the boost frequencies from the ranking in em_compute_costs() and
> keep them all efficient, using the highest non-boost frequency of the
> CPUFreq table, returned by the new helper
> cpufreq_table_max_nonboost_freq(), as the boundary.
>
> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
Please see Sashiko's feedback regarding this patch
https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-v2-1-5a13d1b38d37%40oss.qualcomm.com
and tell me what you think about it.
Thanks!
> ---
> Changes in v2:
> - Drop prev_boost and keep all boost states efficient by resetting
> prev_cost for them, as suggested by Lukasz. Boost states are no
> longer ranked against each other.
> - Retitle the patch to match the new behaviour (was "Rank boost and
> non-boost frequencies separately") and reword the commit message.
>
> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-separately-v1-1-238a6b2bb888@oss.qualcomm.com/
> ---
> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
> kernel/power/energy_model.c | 16 ++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index d3d0d9d02aa4..c93316141a11 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
> return -EINVAL;
> }
>
> +static inline unsigned int
> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> +{
> + struct cpufreq_frequency_table *pos;
> + unsigned int max = 0;
> +
> + if (!policy->freq_table)
> + return 0;
> +
> + /* The table may be unsorted, scan all of it for the highest one. */
> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos->frequency > max)
> + max = pos->frequency;
> + }
> +
> + return max;
> +}
> +
> static inline int parse_perf_domain(int cpu, const char *list_name,
> const char *cell_name,
> struct of_phandle_args *args)
> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
> return -EINVAL;
> }
>
> +static inline unsigned int
> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> +{
> + return 0;
> +}
> +
> static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_name,
> const char *cell_name, struct cpumask *cpumask,
> struct of_phandle_args *pargs)
> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
> index d19a65461ae8..5b1d095fd376 100644
> --- a/kernel/power/energy_model.c
> +++ b/kernel/power/energy_model.c
> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
> unsigned long flags)
> {
> unsigned long prev_cost = ULONG_MAX;
> + struct cpufreq_policy *policy;
> + unsigned int max_nonboost = 0;
> int i, ret;
>
> /* This is needed only for CPUs and EAS skip other devices */
> if (!_is_cpu_device(dev))
> return 0;
>
> + policy = cpufreq_cpu_get(dev->id);
> + if (policy) {
> + max_nonboost = cpufreq_table_max_nonboost_freq(policy);
> + cpufreq_cpu_put(policy);
> + }
> +
> /* Compute the cost of each performance state. */
> for (i = nr_states - 1; i >= 0; i--) {
> unsigned long power_res, cost;
> + bool boost = max_nonboost && table[i].frequency > max_nonboost;
>
> if ((flags & EM_PERF_DOMAIN_ARTIFICIAL) && cb->get_cost) {
> ret = cb->get_cost(dev, table[i].frequency, &cost);
> @@ -284,6 +293,13 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
> table[i].flags = EM_PERF_STATE_INEFFICIENT;
> dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
> table[i].frequency);
> + } else if (boost) {
> + /*
> + * Keep all boost states efficient. Resetting prev_cost
> + * also keeps the highest non-boost state efficient,
> + * then rank the rest on their own.
> + */
> + prev_cost = ULONG_MAX;
> } else {
> prev_cost = table[i].cost;
> }
>
> ---
> base-commit: f1ac44c32cba88ad65dcecd4a279661d14e93651
> base-tree: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> change-id: 20261029-em-rank-boost-separately-a7e7c7d78058
>
> Best regards,
> --
> Guo Chen <guo.chen@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-06 15:15 ` Rafael J. Wysocki (Intel)
@ 2026-11-09 6:47 ` Guo Chen
2026-11-09 9:40 ` Lukasz Luba
0 siblings, 1 reply; 11+ messages in thread
From: Guo Chen @ 2026-11-09 6:47 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel)
Cc: Viresh Kumar, Lukasz Luba, Pavel Machek, Len Brown,
Vincent Donnefort, Matthias Kaehlcke, Rafael J . Wysocki,
linux-pm, linux-kernel, stable, xin.liu, aiqun.yu, tengfei.fan,
tingwei.zhang
On 11/6/2026 11:15 PM, Rafael J. Wysocki (Intel) wrote:
> On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com> wrote:
>> em_compute_costs() ranks all the frequencies of the table, boost ones
>> included. A non-boost frequency can be marked inefficient only because
>> a faster boost frequency has a lower or equal cost, e.g.
>>
>> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>>
>> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
>> skipped by governors rounding down to efficient frequencies (e.g.
>> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
>> the best selectable frequency. Several frequencies can be affected.
>>
>> Exclude the boost frequencies from the ranking in em_compute_costs() and
>> keep them all efficient, using the highest non-boost frequency of the
>> CPUFreq table, returned by the new helper
>> cpufreq_table_max_nonboost_freq(), as the boundary.
>>
>> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
>> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
> Please see Sashiko's feedback regarding this patch
>
> https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-v2-1-5a13d1b38d37%40oss.qualcomm.com
>
> and tell me what you think about it.
>
> Thanks!
Thanks for the review.
I did consider this case. If no policy is found, max_nonboost stays 0 and
the new logic is bypassed, i.e. the ranking falls back to the old
behaviour, which looked like the least intrusive option. I also thought
about warning and returning an error, but most of the in-tree callers of
em_recalc_and_update() ignore the return value (e.g.
em_adjust_new_capacity() and exynos_asv_update_opps()), so the update would
just be dropped without anyone noticing.
>> ---
>> Changes in v2:
>> - Drop prev_boost and keep all boost states efficient by resetting
>> prev_cost for them, as suggested by Lukasz. Boost states are no
>> longer ranked against each other.
>> - Retitle the patch to match the new behaviour (was "Rank boost and
>> non-boost frequencies separately") and reword the commit message.
>>
>> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-separately-v1-1-238a6b2bb888@oss.qualcomm.com/
>> ---
>> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
>> kernel/power/energy_model.c | 16 ++++++++++++++++
>> 2 files changed, 40 insertions(+)
>>
>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>> index d3d0d9d02aa4..c93316141a11 100644
>> --- a/include/linux/cpufreq.h
>> +++ b/include/linux/cpufreq.h
>> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
>> return -EINVAL;
>> }
>>
>> +static inline unsigned int
>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>> +{
>> + struct cpufreq_frequency_table *pos;
>> + unsigned int max = 0;
>> +
>> + if (!policy->freq_table)
>> + return 0;
>> +
>> + /* The table may be unsorted, scan all of it for the highest one. */
>> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
>> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos->frequency > max)
>> + max = pos->frequency;
>> + }
>> +
>> + return max;
>> +}
>> +
>> static inline int parse_perf_domain(int cpu, const char *list_name,
>> const char *cell_name,
>> struct of_phandle_args *args)
>> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
>> return -EINVAL;
>> }
>>
>> +static inline unsigned int
>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>> +{
>> + return 0;
>> +}
>> +
>> static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_name,
>> const char *cell_name, struct cpumask *cpumask,
>> struct of_phandle_args *pargs)
>> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
>> index d19a65461ae8..5b1d095fd376 100644
>> --- a/kernel/power/energy_model.c
>> +++ b/kernel/power/energy_model.c
>> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
>> unsigned long flags)
>> {
>> unsigned long prev_cost = ULONG_MAX;
>> + struct cpufreq_policy *policy;
>> + unsigned int max_nonboost = 0;
>> int i, ret;
>>
>> /* This is needed only for CPUs and EAS skip other devices */
>> if (!_is_cpu_device(dev))
>> return 0;
>>
>> + policy = cpufreq_cpu_get(dev->id);
>> + if (policy) {
>> + max_nonboost = cpufreq_table_max_nonboost_freq(policy);
>> + cpufreq_cpu_put(policy);
>> + }
>> +
The lookup can be made more robust though: on the update paths dev->id may
be offline while other CPUs of the performance domain are online. In v3, if
dev->id has no policy and the performance domain already exists, I will use
an active CPU of the performance domain instead, as
em_cpufreq_update_efficiencies() does, and only warn and fall back to the
old behaviour if that fails as well.
I did not use the performance domain for every lookup because at
registration time dev->em_pd is not assigned yet (it is set after
em_create_perf_table() has returned):
policy = cpufreq_cpu_get(dev->id);
if (!policy && dev->em_pd) {
cpu = cpumask_first_and(em_span_cpus(dev->em_pd), cpu_active_mask);
if (cpu < nr_cpu_ids)
policy = cpufreq_cpu_get(cpu);
}
if (policy) {
max_nonboost = cpufreq_table_max_nonboost_freq(policy);
cpufreq_cpu_put(policy);
} else {
dev_warn(dev, "EM: no CPUFreq policy, boost states are "
"not excluded from the ranking\n");
}
This makes it much less likely to miss the policy, but cannot rule it out:
the CPU can still go offline between picking it and calling
cpufreq_cpu_get(). em_cpufreq_update_efficiencies() has the same
limitation.
Would that work for you?
Thanks,
Guo
>> /* Compute the cost of each performance state. */
>> for (i = nr_states - 1; i >= 0; i--) {
>> unsigned long power_res, cost;
>> + bool boost = max_nonboost && table[i].frequency > max_nonboost;
>>
>> if ((flags & EM_PERF_DOMAIN_ARTIFICIAL) && cb->get_cost) {
>> ret = cb->get_cost(dev, table[i].frequency, &cost);
>> @@ -284,6 +293,13 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table,
>> table[i].flags = EM_PERF_STATE_INEFFICIENT;
>> dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
>> table[i].frequency);
>> + } else if (boost) {
>> + /*
>> + * Keep all boost states efficient. Resetting prev_cost
>> + * also keeps the highest non-boost state efficient,
>> + * then rank the rest on their own.
>> + */
>> + prev_cost = ULONG_MAX;
>> } else {
>> prev_cost = table[i].cost;
>> }
>>
>> ---
>> base-commit: f1ac44c32cba88ad65dcecd4a279661d14e93651
>> base-tree: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
>> change-id: 20261029-em-rank-boost-separately-a7e7c7d78058
>>
>> Best regards,
>> --
>> Guo Chen <guo.chen@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-09 6:47 ` Guo Chen
@ 2026-11-09 9:40 ` Lukasz Luba
2026-11-10 9:49 ` Guo Chen
0 siblings, 1 reply; 11+ messages in thread
From: Lukasz Luba @ 2026-11-09 9:40 UTC (permalink / raw)
To: Guo Chen, Rafael J. Wysocki (Intel)
Cc: Viresh Kumar, Pavel Machek, Len Brown, Vincent Donnefort,
Matthias Kaehlcke, Rafael J . Wysocki, linux-pm, linux-kernel,
stable, xin.liu, aiqun.yu, tengfei.fan, tingwei.zhang
On 11/9/26 06:47, Guo Chen wrote:
>
> On 11/6/2026 11:15 PM, Rafael J. Wysocki (Intel) wrote:
>> On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com>
>> wrote:
>>> em_compute_costs() ranks all the frequencies of the table, boost ones
>>> included. A non-boost frequency can be marked inefficient only because
>>> a faster boost frequency has a lower or equal cost, e.g.
>>>
>>> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>>>
>>> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
>>> skipped by governors rounding down to efficient frequencies (e.g.
>>> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
>>> the best selectable frequency. Several frequencies can be affected.
>>>
>>> Exclude the boost frequencies from the ranking in em_compute_costs() and
>>> keep them all efficient, using the highest non-boost frequency of the
>>> CPUFreq table, returned by the new helper
>>> cpufreq_table_max_nonboost_freq(), as the boundary.
>>>
>>> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
>>> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
>> Please see Sashiko's feedback regarding this patch
>>
>> https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-
>> v2-1-5a13d1b38d37%40oss.qualcomm.com
>>
>> and tell me what you think about it.
>>
>> Thanks!
>
> Thanks for the review.
>
> I did consider this case. If no policy is found, max_nonboost stays 0 and
> the new logic is bypassed, i.e. the ranking falls back to the old
> behaviour, which looked like the least intrusive option. I also thought
> about warning and returning an error, but most of the in-tree callers of
> em_recalc_and_update() ignore the return value (e.g.
> em_adjust_new_capacity() and exynos_asv_update_opps()), so the update would
> just be dropped without anyone noticing.
>
>>> ---
>>> Changes in v2:
>>> - Drop prev_boost and keep all boost states efficient by resetting
>>> prev_cost for them, as suggested by Lukasz. Boost states are no
>>> longer ranked against each other.
>>> - Retitle the patch to match the new behaviour (was "Rank boost and
>>> non-boost frequencies separately") and reword the commit message.
>>>
>>> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-
>>> separately-v1-1-238a6b2bb888@oss.qualcomm.com/
>>> ---
>>> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
>>> kernel/power/energy_model.c | 16 ++++++++++++++++
>>> 2 files changed, 40 insertions(+)
>>>
>>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>>> index d3d0d9d02aa4..c93316141a11 100644
>>> --- a/include/linux/cpufreq.h
>>> +++ b/include/linux/cpufreq.h
>>> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct
>>> cpufreq_policy *policy,
>>> return -EINVAL;
>>> }
>>>
>>> +static inline unsigned int
>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>> +{
>>> + struct cpufreq_frequency_table *pos;
>>> + unsigned int max = 0;
>>> +
>>> + if (!policy->freq_table)
>>> + return 0;
>>> +
>>> + /* The table may be unsorted, scan all of it for the highest
>>> one. */
>>> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
>>> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos-
>>> >frequency > max)
>>> + max = pos->frequency;
>>> + }
>>> +
>>> + return max;
>>> +}
>>> +
>>> static inline int parse_perf_domain(int cpu, const char *list_name,
>>> const char *cell_name,
>>> struct of_phandle_args *args)
>>> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct
>>> cpufreq_policy *policy,
>>> return -EINVAL;
>>> }
>>>
>>> +static inline unsigned int
>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> static inline int of_perf_domain_get_sharing_cpumask(int pcpu,
>>> const char *list_name,
>>> const char
>>> *cell_name, struct cpumask *cpumask,
>>> struct
>>> of_phandle_args *pargs)
>>> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
>>> index d19a65461ae8..5b1d095fd376 100644
>>> --- a/kernel/power/energy_model.c
>>> +++ b/kernel/power/energy_model.c
>>> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev,
>>> struct em_perf_state *table,
>>> unsigned long flags)
>>> {
>>> unsigned long prev_cost = ULONG_MAX;
>>> + struct cpufreq_policy *policy;
>>> + unsigned int max_nonboost = 0;
>>> int i, ret;
>>>
>>> /* This is needed only for CPUs and EAS skip other devices */
>>> if (!_is_cpu_device(dev))
>>> return 0;
>>>
>>> + policy = cpufreq_cpu_get(dev->id);
>>> + if (policy) {
>>> + max_nonboost = cpufreq_table_max_nonboost_freq(policy);
>>> + cpufreq_cpu_put(policy);
>>> + }
>>> +
>
> The lookup can be made more robust though: on the update paths dev->id may
> be offline while other CPUs of the performance domain are online. In v3, if
> dev->id has no policy and the performance domain already exists, I will use
> an active CPU of the performance domain instead, as
> em_cpufreq_update_efficiencies() does, and only warn and fall back to the
> old behaviour if that fails as well.
>
> I did not use the performance domain for every lookup because at
> registration time dev->em_pd is not assigned yet (it is set after
> em_create_perf_table() has returned):
>
> policy = cpufreq_cpu_get(dev->id);
> if (!policy && dev->em_pd) {
> cpu = cpumask_first_and(em_span_cpus(dev->em_pd), cpu_active_mask);
> if (cpu < nr_cpu_ids)
> policy = cpufreq_cpu_get(cpu);
> }
>
> if (policy) {
> max_nonboost = cpufreq_table_max_nonboost_freq(policy);
> cpufreq_cpu_put(policy);
> } else {
> dev_warn(dev, "EM: no CPUFreq policy, boost states are "
> "not excluded from the ranking\n");
> }
>
> This makes it much less likely to miss the policy, but cannot rule it out:
> the CPU can still go offline between picking it and calling
> cpufreq_cpu_get(). em_cpufreq_update_efficiencies() has the same
> limitation.
>
> Would that work for you?
I also thought about that possible racy corner case, where
CPU can go offline (or already be offline). Although, in current
usage this should be OK, since we do this in boot phase and
platforms are sane.
We can can add that step with 'cpu_active_mask' to play safe,
but no hard promises it would be atomic.
The warning also would help, for bring-up phase, so engineers would
notice it and address the racy hot-plug booting system when it's there.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-09 9:40 ` Lukasz Luba
@ 2026-11-10 9:49 ` Guo Chen
2026-11-10 9:58 ` Lukasz Luba
0 siblings, 1 reply; 11+ messages in thread
From: Guo Chen @ 2026-11-10 9:49 UTC (permalink / raw)
To: Lukasz Luba, Rafael J. Wysocki (Intel)
Cc: Viresh Kumar, Pavel Machek, Len Brown, Vincent Donnefort,
Matthias Kaehlcke, Rafael J . Wysocki, linux-pm, linux-kernel,
stable, xin.liu, aiqun.yu, tengfei.fan, tingwei.zhang
On 11/9/2026 5:40 PM, Lukasz Luba wrote:
>
>
> On 11/9/26 06:47, Guo Chen wrote:
>>
>> On 11/6/2026 11:15 PM, Rafael J. Wysocki (Intel) wrote:
>>> On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com>
>>> wrote:
>>>> em_compute_costs() ranks all the frequencies of the table, boost ones
>>>> included. A non-boost frequency can be marked inefficient only because
>>>> a faster boost frequency has a lower or equal cost, e.g.
>>>>
>>>> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>>>>
>>>> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
>>>> skipped by governors rounding down to efficient frequencies (e.g.
>>>> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
>>>> the best selectable frequency. Several frequencies can be affected.
>>>>
>>>> Exclude the boost frequencies from the ranking in
>>>> em_compute_costs() and
>>>> keep them all efficient, using the highest non-boost frequency of the
>>>> CPUFreq table, returned by the new helper
>>>> cpufreq_table_max_nonboost_freq(), as the boundary.
>>>>
>>>> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
>>>> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
>>> Please see Sashiko's feedback regarding this patch
>>>
>>> https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-
>>> v2-1-5a13d1b38d37%40oss.qualcomm.com
>>>
>>> and tell me what you think about it.
>>>
>>> Thanks!
>>
>> Thanks for the review.
>>
>> I did consider this case. If no policy is found, max_nonboost stays 0
>> and
>> the new logic is bypassed, i.e. the ranking falls back to the old
>> behaviour, which looked like the least intrusive option. I also thought
>> about warning and returning an error, but most of the in-tree callers of
>> em_recalc_and_update() ignore the return value (e.g.
>> em_adjust_new_capacity() and exynos_asv_update_opps()), so the update
>> would
>> just be dropped without anyone noticing.
>>
>>>> ---
>>>> Changes in v2:
>>>> - Drop prev_boost and keep all boost states efficient by resetting
>>>> prev_cost for them, as suggested by Lukasz. Boost states are no
>>>> longer ranked against each other.
>>>> - Retitle the patch to match the new behaviour (was "Rank boost and
>>>> non-boost frequencies separately") and reword the commit message.
>>>>
>>>> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-
>>>> separately-v1-1-238a6b2bb888@oss.qualcomm.com/
>>>> ---
>>>> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
>>>> kernel/power/energy_model.c | 16 ++++++++++++++++
>>>> 2 files changed, 40 insertions(+)
>>>>
>>>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>>>> index d3d0d9d02aa4..c93316141a11 100644
>>>> --- a/include/linux/cpufreq.h
>>>> +++ b/include/linux/cpufreq.h
>>>> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct
>>>> cpufreq_policy *policy,
>>>> return -EINVAL;
>>>> }
>>>>
>>>> +static inline unsigned int
>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>>> +{
>>>> + struct cpufreq_frequency_table *pos;
>>>> + unsigned int max = 0;
>>>> +
>>>> + if (!policy->freq_table)
>>>> + return 0;
>>>> +
>>>> + /* The table may be unsorted, scan all of it for the
>>>> highest one. */
>>>> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
>>>> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos-
>>>> >frequency > max)
>>>> + max = pos->frequency;
>>>> + }
>>>> +
>>>> + return max;
>>>> +}
>>>> +
>>>> static inline int parse_perf_domain(int cpu, const char *list_name,
>>>> const char *cell_name,
>>>> struct of_phandle_args *args)
>>>> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct
>>>> cpufreq_policy *policy,
>>>> return -EINVAL;
>>>> }
>>>>
>>>> +static inline unsigned int
>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>>> +{
>>>> + return 0;
>>>> +}
>>>> +
>>>> static inline int of_perf_domain_get_sharing_cpumask(int pcpu,
>>>> const char *list_name,
>>>> const char
>>>> *cell_name, struct cpumask *cpumask,
>>>> struct
>>>> of_phandle_args *pargs)
>>>> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
>>>> index d19a65461ae8..5b1d095fd376 100644
>>>> --- a/kernel/power/energy_model.c
>>>> +++ b/kernel/power/energy_model.c
>>>> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device
>>>> *dev, struct em_perf_state *table,
>>>> unsigned long flags)
>>>> {
>>>> unsigned long prev_cost = ULONG_MAX;
>>>> + struct cpufreq_policy *policy;
>>>> + unsigned int max_nonboost = 0;
>>>> int i, ret;
>>>>
>>>> /* This is needed only for CPUs and EAS skip other devices */
>>>> if (!_is_cpu_device(dev))
>>>> return 0;
>>>>
>>>> + policy = cpufreq_cpu_get(dev->id);
>>>> + if (policy) {
>>>> + max_nonboost =
>>>> cpufreq_table_max_nonboost_freq(policy);
>>>> + cpufreq_cpu_put(policy);
>>>> + }
>>>> +
>>
>> The lookup can be made more robust though: on the update paths
>> dev->id may
>> be offline while other CPUs of the performance domain are online. In
>> v3, if
>> dev->id has no policy and the performance domain already exists, I
>> will use
>> an active CPU of the performance domain instead, as
>> em_cpufreq_update_efficiencies() does, and only warn and fall back to
>> the
>> old behaviour if that fails as well.
>>
>> I did not use the performance domain for every lookup because at
>> registration time dev->em_pd is not assigned yet (it is set after
>> em_create_perf_table() has returned):
>>
>> policy = cpufreq_cpu_get(dev->id);
>> if (!policy && dev->em_pd) {
>> cpu = cpumask_first_and(em_span_cpus(dev->em_pd), cpu_active_mask);
>> if (cpu < nr_cpu_ids)
>> policy = cpufreq_cpu_get(cpu);
>> }
>>
>> if (policy) {
>> max_nonboost = cpufreq_table_max_nonboost_freq(policy);
>> cpufreq_cpu_put(policy);
>> } else {
>> dev_warn(dev, "EM: no CPUFreq policy, boost states are "
>> "not excluded from the ranking\n");
>> }
>>
>> This makes it much less likely to miss the policy, but cannot rule it
>> out:
>> the CPU can still go offline between picking it and calling
>> cpufreq_cpu_get(). em_cpufreq_update_efficiencies() has the same
>> limitation.
>>
>> Would that work for you?
> I also thought about that possible racy corner case, where
> CPU can go offline (or already be offline). Although, in current
> usage this should be OK, since we do this in boot phase and
> platforms are sane.
>
> We can can add that step with 'cpu_active_mask' to play safe,
> but no hard promises it would be atomic.
>
> The warning also would help, for bring-up phase, so engineers would
> notice it and address the racy hot-plug booting system when it's there.
Thanks Lukasz,
I’ll add the 'cpu_active_mask' check and the warning in v3. As the
overall approach is unchanged, I’ll keep your reviewed-by.
Please let me know if you’d rather have it removed.
Thanks,
Guo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-10 9:49 ` Guo Chen
@ 2026-11-10 9:58 ` Lukasz Luba
2026-11-10 12:15 ` Rafael J. Wysocki (Intel)
0 siblings, 1 reply; 11+ messages in thread
From: Lukasz Luba @ 2026-11-10 9:58 UTC (permalink / raw)
To: Guo Chen
Cc: Viresh Kumar, Pavel Machek, Len Brown, Vincent Donnefort,
Matthias Kaehlcke, Rafael J . Wysocki, linux-pm, linux-kernel,
stable, xin.liu, aiqun.yu, tengfei.fan, tingwei.zhang,
Rafael J. Wysocki (Intel)
On 11/10/26 09:49, Guo Chen wrote:
>
> On 11/9/2026 5:40 PM, Lukasz Luba wrote:
>>
>>
>> On 11/9/26 06:47, Guo Chen wrote:
>>>
>>> On 11/6/2026 11:15 PM, Rafael J. Wysocki (Intel) wrote:
>>>> On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com>
>>>> wrote:
>>>>> em_compute_costs() ranks all the frequencies of the table, boost ones
>>>>> included. A non-boost frequency can be marked inefficient only because
>>>>> a faster boost frequency has a lower or equal cost, e.g.
>>>>>
>>>>> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
>>>>>
>>>>> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
>>>>> skipped by governors rounding down to efficient frequencies (e.g.
>>>>> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
>>>>> the best selectable frequency. Several frequencies can be affected.
>>>>>
>>>>> Exclude the boost frequencies from the ranking in
>>>>> em_compute_costs() and
>>>>> keep them all efficient, using the highest non-boost frequency of the
>>>>> CPUFreq table, returned by the new helper
>>>>> cpufreq_table_max_nonboost_freq(), as the boundary.
>>>>>
>>>>> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
>>>>> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
>>>> Please see Sashiko's feedback regarding this patch
>>>>
>>>> https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-
>>>> v2-1-5a13d1b38d37%40oss.qualcomm.com
>>>>
>>>> and tell me what you think about it.
>>>>
>>>> Thanks!
>>>
>>> Thanks for the review.
>>>
>>> I did consider this case. If no policy is found, max_nonboost stays 0
>>> and
>>> the new logic is bypassed, i.e. the ranking falls back to the old
>>> behaviour, which looked like the least intrusive option. I also thought
>>> about warning and returning an error, but most of the in-tree callers of
>>> em_recalc_and_update() ignore the return value (e.g.
>>> em_adjust_new_capacity() and exynos_asv_update_opps()), so the update
>>> would
>>> just be dropped without anyone noticing.
>>>
>>>>> ---
>>>>> Changes in v2:
>>>>> - Drop prev_boost and keep all boost states efficient by resetting
>>>>> prev_cost for them, as suggested by Lukasz. Boost states are no
>>>>> longer ranked against each other.
>>>>> - Retitle the patch to match the new behaviour (was "Rank boost and
>>>>> non-boost frequencies separately") and reword the commit message.
>>>>>
>>>>> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-
>>>>> separately-v1-1-238a6b2bb888@oss.qualcomm.com/
>>>>> ---
>>>>> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
>>>>> kernel/power/energy_model.c | 16 ++++++++++++++++
>>>>> 2 files changed, 40 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>>>>> index d3d0d9d02aa4..c93316141a11 100644
>>>>> --- a/include/linux/cpufreq.h
>>>>> +++ b/include/linux/cpufreq.h
>>>>> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct
>>>>> cpufreq_policy *policy,
>>>>> return -EINVAL;
>>>>> }
>>>>>
>>>>> +static inline unsigned int
>>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>>>> +{
>>>>> + struct cpufreq_frequency_table *pos;
>>>>> + unsigned int max = 0;
>>>>> +
>>>>> + if (!policy->freq_table)
>>>>> + return 0;
>>>>> +
>>>>> + /* The table may be unsorted, scan all of it for the
>>>>> highest one. */
>>>>> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
>>>>> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos-
>>>>> >frequency > max)
>>>>> + max = pos->frequency;
>>>>> + }
>>>>> +
>>>>> + return max;
>>>>> +}
>>>>> +
>>>>> static inline int parse_perf_domain(int cpu, const char *list_name,
>>>>> const char *cell_name,
>>>>> struct of_phandle_args *args)
>>>>> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct
>>>>> cpufreq_policy *policy,
>>>>> return -EINVAL;
>>>>> }
>>>>>
>>>>> +static inline unsigned int
>>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
>>>>> +{
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> static inline int of_perf_domain_get_sharing_cpumask(int pcpu,
>>>>> const char *list_name,
>>>>> const char
>>>>> *cell_name, struct cpumask *cpumask,
>>>>> struct
>>>>> of_phandle_args *pargs)
>>>>> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
>>>>> index d19a65461ae8..5b1d095fd376 100644
>>>>> --- a/kernel/power/energy_model.c
>>>>> +++ b/kernel/power/energy_model.c
>>>>> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device
>>>>> *dev, struct em_perf_state *table,
>>>>> unsigned long flags)
>>>>> {
>>>>> unsigned long prev_cost = ULONG_MAX;
>>>>> + struct cpufreq_policy *policy;
>>>>> + unsigned int max_nonboost = 0;
>>>>> int i, ret;
>>>>>
>>>>> /* This is needed only for CPUs and EAS skip other devices */
>>>>> if (!_is_cpu_device(dev))
>>>>> return 0;
>>>>>
>>>>> + policy = cpufreq_cpu_get(dev->id);
>>>>> + if (policy) {
>>>>> + max_nonboost =
>>>>> cpufreq_table_max_nonboost_freq(policy);
>>>>> + cpufreq_cpu_put(policy);
>>>>> + }
>>>>> +
>>>
>>> The lookup can be made more robust though: on the update paths dev-
>>> >id may
>>> be offline while other CPUs of the performance domain are online. In
>>> v3, if
>>> dev->id has no policy and the performance domain already exists, I
>>> will use
>>> an active CPU of the performance domain instead, as
>>> em_cpufreq_update_efficiencies() does, and only warn and fall back to
>>> the
>>> old behaviour if that fails as well.
>>>
>>> I did not use the performance domain for every lookup because at
>>> registration time dev->em_pd is not assigned yet (it is set after
>>> em_create_perf_table() has returned):
>>>
>>> policy = cpufreq_cpu_get(dev->id);
>>> if (!policy && dev->em_pd) {
>>> cpu = cpumask_first_and(em_span_cpus(dev->em_pd), cpu_active_mask);
>>> if (cpu < nr_cpu_ids)
>>> policy = cpufreq_cpu_get(cpu);
>>> }
>>>
>>> if (policy) {
>>> max_nonboost = cpufreq_table_max_nonboost_freq(policy);
>>> cpufreq_cpu_put(policy);
>>> } else {
>>> dev_warn(dev, "EM: no CPUFreq policy, boost states are "
>>> "not excluded from the ranking\n");
>>> }
>>>
>>> This makes it much less likely to miss the policy, but cannot rule it
>>> out:
>>> the CPU can still go offline between picking it and calling
>>> cpufreq_cpu_get(). em_cpufreq_update_efficiencies() has the same
>>> limitation.
>>>
>>> Would that work for you?
>> I also thought about that possible racy corner case, where
>> CPU can go offline (or already be offline). Although, in current
>> usage this should be OK, since we do this in boot phase and
>> platforms are sane.
>>
>> We can can add that step with 'cpu_active_mask' to play safe,
>> but no hard promises it would be atomic.
>>
>> The warning also would help, for bring-up phase, so engineers would
>> notice it and address the racy hot-plug booting system when it's there.
>
> Thanks Lukasz,
>
> I’ll add the 'cpu_active_mask' check and the warning in v3. As the
> overall approach is unchanged, I’ll keep your reviewed-by.
> Please let me know if you’d rather have it removed.
That's fine, please continue.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-10 9:58 ` Lukasz Luba
@ 2026-11-10 12:15 ` Rafael J. Wysocki (Intel)
2026-11-10 13:11 ` Lukasz Luba
0 siblings, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-11-10 12:15 UTC (permalink / raw)
To: Lukasz Luba, Guo Chen
Cc: Viresh Kumar, Vincent Donnefort, Matthias Kaehlcke, linux-pm,
linux-kernel, stable, xin.liu, aiqun.yu, tengfei.fan,
tingwei.zhang, Rafael J. Wysocki (Intel)
On Tue, Nov 10, 2026 at 10:58 AM Lukasz Luba <lukasz.luba@arm.com> wrote:
>
>
>
> On 11/10/26 09:49, Guo Chen wrote:
> >
> > On 11/9/2026 5:40 PM, Lukasz Luba wrote:
> >>
> >>
> >> On 11/9/26 06:47, Guo Chen wrote:
> >>>
> >>> On 11/6/2026 11:15 PM, Rafael J. Wysocki (Intel) wrote:
> >>>> On Tue, Nov 3, 2026 at 12:21 PM Guo Chen <guo.chen@oss.qualcomm.com>
> >>>> wrote:
> >>>>> em_compute_costs() ranks all the frequencies of the table, boost ones
> >>>>> included. A non-boost frequency can be marked inefficient only because
> >>>>> a faster boost frequency has a lower or equal cost, e.g.
> >>>>>
> >>>>> 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C)
> >>>>>
> >>>>> With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still
> >>>>> skipped by governors rounding down to efficient frequencies (e.g.
> >>>>> ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of
> >>>>> the best selectable frequency. Several frequencies can be affected.
> >>>>>
> >>>>> Exclude the boost frequencies from the ranking in
> >>>>> em_compute_costs() and
> >>>>> keep them all efficient, using the highest non-boost frequency of the
> >>>>> CPUFreq table, returned by the new helper
> >>>>> cpufreq_table_max_nonboost_freq(), as the boundary.
> >>>>>
> >>>>> Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states")
> >>>>> Signed-off-by: Guo Chen <guo.chen@oss.qualcomm.com>
> >>>> Please see Sashiko's feedback regarding this patch
> >>>>
> >>>> https://sashiko.dev/#/patchset/20261103-em-rank-boost-separately-
> >>>> v2-1-5a13d1b38d37%40oss.qualcomm.com
> >>>>
> >>>> and tell me what you think about it.
> >>>>
> >>>> Thanks!
> >>>
> >>> Thanks for the review.
> >>>
> >>> I did consider this case. If no policy is found, max_nonboost stays 0
> >>> and
> >>> the new logic is bypassed, i.e. the ranking falls back to the old
> >>> behaviour, which looked like the least intrusive option. I also thought
> >>> about warning and returning an error, but most of the in-tree callers of
> >>> em_recalc_and_update() ignore the return value (e.g.
> >>> em_adjust_new_capacity() and exynos_asv_update_opps()), so the update
> >>> would
> >>> just be dropped without anyone noticing.
> >>>
> >>>>> ---
> >>>>> Changes in v2:
> >>>>> - Drop prev_boost and keep all boost states efficient by resetting
> >>>>> prev_cost for them, as suggested by Lukasz. Boost states are no
> >>>>> longer ranked against each other.
> >>>>> - Retitle the patch to match the new behaviour (was "Rank boost and
> >>>>> non-boost frequencies separately") and reword the commit message.
> >>>>>
> >>>>> Link to v1: https://lore.kernel.org/all/20261030-em-rank-boost-
> >>>>> separately-v1-1-238a6b2bb888@oss.qualcomm.com/
> >>>>> ---
> >>>>> include/linux/cpufreq.h | 24 ++++++++++++++++++++++++
> >>>>> kernel/power/energy_model.c | 16 ++++++++++++++++
> >>>>> 2 files changed, 40 insertions(+)
> >>>>>
> >>>>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> >>>>> index d3d0d9d02aa4..c93316141a11 100644
> >>>>> --- a/include/linux/cpufreq.h
> >>>>> +++ b/include/linux/cpufreq.h
> >>>>> @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct
> >>>>> cpufreq_policy *policy,
> >>>>> return -EINVAL;
> >>>>> }
> >>>>>
> >>>>> +static inline unsigned int
> >>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> >>>>> +{
> >>>>> + struct cpufreq_frequency_table *pos;
> >>>>> + unsigned int max = 0;
> >>>>> +
> >>>>> + if (!policy->freq_table)
> >>>>> + return 0;
> >>>>> +
> >>>>> + /* The table may be unsorted, scan all of it for the
> >>>>> highest one. */
> >>>>> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
> >>>>> + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos-
> >>>>> >frequency > max)
> >>>>> + max = pos->frequency;
> >>>>> + }
> >>>>> +
> >>>>> + return max;
> >>>>> +}
> >>>>> +
> >>>>> static inline int parse_perf_domain(int cpu, const char *list_name,
> >>>>> const char *cell_name,
> >>>>> struct of_phandle_args *args)
> >>>>> @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct
> >>>>> cpufreq_policy *policy,
> >>>>> return -EINVAL;
> >>>>> }
> >>>>>
> >>>>> +static inline unsigned int
> >>>>> +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy)
> >>>>> +{
> >>>>> + return 0;
> >>>>> +}
> >>>>> +
> >>>>> static inline int of_perf_domain_get_sharing_cpumask(int pcpu,
> >>>>> const char *list_name,
> >>>>> const char
> >>>>> *cell_name, struct cpumask *cpumask,
> >>>>> struct
> >>>>> of_phandle_args *pargs)
> >>>>> diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
> >>>>> index d19a65461ae8..5b1d095fd376 100644
> >>>>> --- a/kernel/power/energy_model.c
> >>>>> +++ b/kernel/power/energy_model.c
> >>>>> @@ -255,15 +255,24 @@ static int em_compute_costs(struct device
> >>>>> *dev, struct em_perf_state *table,
> >>>>> unsigned long flags)
> >>>>> {
> >>>>> unsigned long prev_cost = ULONG_MAX;
> >>>>> + struct cpufreq_policy *policy;
> >>>>> + unsigned int max_nonboost = 0;
> >>>>> int i, ret;
> >>>>>
> >>>>> /* This is needed only for CPUs and EAS skip other devices */
> >>>>> if (!_is_cpu_device(dev))
> >>>>> return 0;
> >>>>>
> >>>>> + policy = cpufreq_cpu_get(dev->id);
> >>>>> + if (policy) {
> >>>>> + max_nonboost =
> >>>>> cpufreq_table_max_nonboost_freq(policy);
> >>>>> + cpufreq_cpu_put(policy);
> >>>>> + }
> >>>>> +
> >>>
> >>> The lookup can be made more robust though: on the update paths dev-
> >>> >id may
> >>> be offline while other CPUs of the performance domain are online. In
> >>> v3, if
> >>> dev->id has no policy and the performance domain already exists, I
> >>> will use
> >>> an active CPU of the performance domain instead, as
> >>> em_cpufreq_update_efficiencies() does, and only warn and fall back to
> >>> the
> >>> old behaviour if that fails as well.
> >>>
> >>> I did not use the performance domain for every lookup because at
> >>> registration time dev->em_pd is not assigned yet (it is set after
> >>> em_create_perf_table() has returned):
> >>>
> >>> policy = cpufreq_cpu_get(dev->id);
> >>> if (!policy && dev->em_pd) {
> >>> cpu = cpumask_first_and(em_span_cpus(dev->em_pd), cpu_active_mask);
> >>> if (cpu < nr_cpu_ids)
> >>> policy = cpufreq_cpu_get(cpu);
> >>> }
> >>>
> >>> if (policy) {
> >>> max_nonboost = cpufreq_table_max_nonboost_freq(policy);
> >>> cpufreq_cpu_put(policy);
> >>> } else {
> >>> dev_warn(dev, "EM: no CPUFreq policy, boost states are "
> >>> "not excluded from the ranking\n");
> >>> }
> >>>
> >>> This makes it much less likely to miss the policy, but cannot rule it
> >>> out:
> >>> the CPU can still go offline between picking it and calling
> >>> cpufreq_cpu_get(). em_cpufreq_update_efficiencies() has the same
> >>> limitation.
> >>>
> >>> Would that work for you?
> >> I also thought about that possible racy corner case, where
> >> CPU can go offline (or already be offline). Although, in current
> >> usage this should be OK, since we do this in boot phase and
> >> platforms are sane.
> >>
> >> We can can add that step with 'cpu_active_mask' to play safe,
> >> but no hard promises it would be atomic.
> >>
> >> The warning also would help, for bring-up phase, so engineers would
> >> notice it and address the racy hot-plug booting system when it's there.
> >
> > Thanks Lukasz,
> >
> > I’ll add the 'cpu_active_mask' check and the warning in v3. As the
> > overall approach is unchanged, I’ll keep your reviewed-by.
> > Please let me know if you’d rather have it removed.
>
> That's fine, please continue.
I have a couple of questions though.
First, why is the ondemand governor mentioned in the changelog? In
the mainline, the ondemand governor cannot work with EAS, so it
shouldn't matter for this issue, should it?
Second, why is the issue regarded as a defect in the code and not in
the energy model? Arguably, boost frequencies should be more costly
than the non-boost ones. At least the idea behind the boost is making
higher-cost OPPs temporarily available. If they are sustainable,
treating them as boost OPPs is rather pointless.
TBH, I'm too comfortable with looking at cpufreq frequency from within
the EM code. If that needs to be done, something is amiss at the
design level.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-10 12:15 ` Rafael J. Wysocki (Intel)
@ 2026-11-10 13:11 ` Lukasz Luba
2026-11-10 13:43 ` Rafael J. Wysocki (Intel)
0 siblings, 1 reply; 11+ messages in thread
From: Lukasz Luba @ 2026-11-10 13:11 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel)
Cc: Viresh Kumar, Guo Chen, Vincent Donnefort, Matthias Kaehlcke,
linux-pm, linux-kernel, stable, xin.liu, aiqun.yu, tengfei.fan,
tingwei.zhang
Hi Rafael,
On 11/10/26 12:15, Rafael J. Wysocki (Intel) wrote:
> On Tue, Nov 10, 2026 at 10:58 AM Lukasz Luba <lukasz.luba@arm.com> wrote:
[snip]
>>
>> That's fine, please continue.
>
> I have a couple of questions though.
>
> First, why is the ondemand governor mentioned in the changelog? In
> the mainline, the ondemand governor cannot work with EAS, so it
> shouldn't matter for this issue, should it?
The ondemand is affected by the EM setup code and set 'inefficient'
flags for some OPPs. The EM is also present for cooling devices
and can work w/o EAS and schedutil, w/ just ondemand governor.
Because EM marks the OPPs kind of 'globally' as inefficient, then
they become CPUFREQ_INEFFICIENT_FREQ entries in the CPUfreq fwk.
In the EM code we have:
cpufreq_table_set_inefficient(policy, table[i].frequency);
Then ondemand check for CPUFREQ_RELATION_HE will skip them and
pass to __cpufreq_driver_target() with that flags as well.
>
> Second, why is the issue regarded as a defect in the code and not in
> the energy model? Arguably, boost frequencies should be more costly
> than the non-boost ones. At least the idea behind the boost is making
> higher-cost OPPs temporarily available. If they are sustainable,
> treating them as boost OPPs is rather pointless.
IMHO it was a bug in the commit mentioned in this patch fix tag.
It is affecting more than just EAS or EM, since the EM is working with
all generic code and all cpufreq governors.
>
> TBH, I'm too comfortable with looking at cpufreq frequency from within
> the EM code. If that needs to be done, something is amiss at the
> design level.
I think this edge case is special, as I described above.
I'm happy to hear your view on this EM influence to some global
setting in cpufreq. Maybe it was too far to establish this
'inefficiency' flags in there for many usage?
Regards,
Lukasz
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-10 13:11 ` Lukasz Luba
@ 2026-11-10 13:43 ` Rafael J. Wysocki (Intel)
2026-11-10 14:05 ` Lukasz Luba
0 siblings, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-11-10 13:43 UTC (permalink / raw)
To: Lukasz Luba
Cc: Rafael J. Wysocki (Intel),
Viresh Kumar, Guo Chen, Vincent Donnefort, Matthias Kaehlcke,
linux-pm, linux-kernel, stable, xin.liu, aiqun.yu, tengfei.fan,
tingwei.zhang
On Tue, Nov 10, 2026 at 2:11 PM Lukasz Luba <lukasz.luba@arm.com> wrote:
>
> Hi Rafael,
>
> On 11/10/26 12:15, Rafael J. Wysocki (Intel) wrote:
> > On Tue, Nov 10, 2026 at 10:58 AM Lukasz Luba <lukasz.luba@arm.com> wrote:
>
> [snip]
>
>
> >>
> >> That's fine, please continue.
> >
> > I have a couple of questions though.
> >
> > First, why is the ondemand governor mentioned in the changelog? In
> > the mainline, the ondemand governor cannot work with EAS, so it
> > shouldn't matter for this issue, should it?
>
> The ondemand is affected by the EM setup code and set 'inefficient'
> flags for some OPPs. The EM is also present for cooling devices
> and can work w/o EAS and schedutil, w/ just ondemand governor.
>
> Because EM marks the OPPs kind of 'globally' as inefficient, then
> they become CPUFREQ_INEFFICIENT_FREQ entries in the CPUfreq fwk.
> In the EM code we have:
> cpufreq_table_set_inefficient(policy, table[i].frequency);
So maybe this is the one that needs to be fixed? What about simply
skipping boost frequencies in it?
> Then ondemand check for CPUFREQ_RELATION_HE will skip them and
> pass to __cpufreq_driver_target() with that flags as well.
Thanks for explaining and all of that needs to be said in the patch changelog.
> >
> > Second, why is the issue regarded as a defect in the code and not in
> > the energy model? Arguably, boost frequencies should be more costly
> > than the non-boost ones. At least the idea behind the boost is making
> > higher-cost OPPs temporarily available. If they are sustainable,
> > treating them as boost OPPs is rather pointless.
>
> IMHO it was a bug in the commit mentioned in this patch fix tag.
> It is affecting more than just EAS or EM, since the EM is working with
> all generic code and all cpufreq governors.
To be precise, the EM initialization may affect cpufreq in general
because inefficient frequencies are used for CPU cooling. Fair
enough, but I'm not talking about this.
I'm talking about a reason for giving boost frequencies lower or equal
cost relative to non-boost frequencies in the energy model because
this doesn't make sense to me TBH.
And I get that such energy models were there before the commit in
question and now they are not working properly, but IMO they are
broken, not that commit.
> >
> > TBH, I'm too comfortable with looking at cpufreq frequency from within
> > the EM code. If that needs to be done, something is amiss at the
> > design level.
>
> I think this edge case is special, as I described above.
>
> I'm happy to hear your view on this EM influence to some global
> setting in cpufreq. Maybe it was too far to establish this
> 'inefficiency' flags in there for many usage?
There's nothing wrong with using the information from the energy
model, when available, to amend cpufreq, but the patch goes the other
way around: It tries to amend the energy model with information taken
from cpufreq (in order to avoid making mistakes later when amending
cpufreq with the energy model information).
I think that cpufreq should simply refuse to set
CPUFREQ_INEFFICIENT_FREQ for boost frequencies. Wouldn't that work?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking
2026-11-10 13:43 ` Rafael J. Wysocki (Intel)
@ 2026-11-10 14:05 ` Lukasz Luba
0 siblings, 0 replies; 11+ messages in thread
From: Lukasz Luba @ 2026-11-10 14:05 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel)
Cc: Viresh Kumar, Guo Chen, Vincent Donnefort, Matthias Kaehlcke,
linux-pm, linux-kernel, stable, xin.liu, aiqun.yu, tengfei.fan,
tingwei.zhang
On 11/10/26 13:43, Rafael J. Wysocki (Intel) wrote:
> On Tue, Nov 10, 2026 at 2:11 PM Lukasz Luba <lukasz.luba@arm.com> wrote:
>>
>> Hi Rafael,
>>
>> On 11/10/26 12:15, Rafael J. Wysocki (Intel) wrote:
>>> On Tue, Nov 10, 2026 at 10:58 AM Lukasz Luba <lukasz.luba@arm.com> wrote:
>>
>> [snip]
>>
>>
>>>>
>>>> That's fine, please continue.
>>>
>>> I have a couple of questions though.
>>>
>>> First, why is the ondemand governor mentioned in the changelog? In
>>> the mainline, the ondemand governor cannot work with EAS, so it
>>> shouldn't matter for this issue, should it?
>>
>> The ondemand is affected by the EM setup code and set 'inefficient'
>> flags for some OPPs. The EM is also present for cooling devices
>> and can work w/o EAS and schedutil, w/ just ondemand governor.
>>
>> Because EM marks the OPPs kind of 'globally' as inefficient, then
>> they become CPUFREQ_INEFFICIENT_FREQ entries in the CPUfreq fwk.
>> In the EM code we have:
>> cpufreq_table_set_inefficient(policy, table[i].frequency);
>
> So maybe this is the one that needs to be fixed? What about simply
> skipping boost frequencies in it?
>
>> Then ondemand check for CPUFREQ_RELATION_HE will skip them and
>> pass to __cpufreq_driver_target() with that flags as well.
>
> Thanks for explaining and all of that needs to be said in the patch changelog.
>
>>>
>>> Second, why is the issue regarded as a defect in the code and not in
>>> the energy model? Arguably, boost frequencies should be more costly
>>> than the non-boost ones. At least the idea behind the boost is making
>>> higher-cost OPPs temporarily available. If they are sustainable,
>>> treating them as boost OPPs is rather pointless.
>>
>> IMHO it was a bug in the commit mentioned in this patch fix tag.
>> It is affecting more than just EAS or EM, since the EM is working with
>> all generic code and all cpufreq governors.
>
> To be precise, the EM initialization may affect cpufreq in general
> because inefficient frequencies are used for CPU cooling. Fair
> enough, but I'm not talking about this.
>
> I'm talking about a reason for giving boost frequencies lower or equal
> cost relative to non-boost frequencies in the energy model because
> this doesn't make sense to me TBH.
>
> And I get that such energy models were there before the commit in
> question and now they are not working properly, but IMO they are
> broken, not that commit.
>
>>>
>>> TBH, I'm too comfortable with looking at cpufreq frequency from within
>>> the EM code. If that needs to be done, something is amiss at the
>>> design level.
>>
>> I think this edge case is special, as I described above.
>>
>> I'm happy to hear your view on this EM influence to some global
>> setting in cpufreq. Maybe it was too far to establish this
>> 'inefficiency' flags in there for many usage?
>
> There's nothing wrong with using the information from the energy
> model, when available, to amend cpufreq, but the patch goes the other
> way around: It tries to amend the energy model with information taken
> from cpufreq (in order to avoid making mistakes later when amending
> cpufreq with the energy model information).
>
> I think that cpufreq should simply refuse to set
> CPUFREQ_INEFFICIENT_FREQ for boost frequencies. Wouldn't that work?
I see your point now, about the direction. Yes, you're right.
Since we are taking the information about 'boost' from the
cpufreq, then refusing to set OPPs inefficient in the first
place makes more sense.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-11-10 14:04 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 11:21 [PATCH v2] PM: EM: Exclude boost frequencies from inefficiency ranking Guo Chen
2026-11-05 13:23 ` Lukasz Luba
2026-11-06 15:15 ` Rafael J. Wysocki (Intel)
2026-11-09 6:47 ` Guo Chen
2026-11-09 9:40 ` Lukasz Luba
2026-11-10 9:49 ` Guo Chen
2026-11-10 9:58 ` Lukasz Luba
2026-11-10 12:15 ` Rafael J. Wysocki (Intel)
2026-11-10 13:11 ` Lukasz Luba
2026-11-10 13:43 ` Rafael J. Wysocki (Intel)
2026-11-10 14:05 ` Lukasz Luba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®