Skip to content

Commit 3f25e32

Browse files
committed
cpufreq: Fix setting policy limits when frequency tables are used
JIRA: https://issues.redhat.com/browse/RHEL-83803 commit b790280 Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Mon, 28 Apr 2025 14:36:41 +0000 Commit 7491cdf ("cpufreq: Avoid using inconsistent policy->min and policy->max") overlooked the fact that policy->min and policy->max were accessed directly in cpufreq_frequency_table_target() and in the functions called by it. Consequently, the changes made by that commit led to problems with setting policy limits. Address this by passing the target frequency limits to __resolve_freq() and cpufreq_frequency_table_target() and propagating them to the functions called by the latter. Fixes: 7491cdf ("cpufreq: Avoid using inconsistent policy->min and policy->max") Cc: 5.16+ <stable@vger.kernel.org> # 5.16+ Closes: https://lore.kernel.org/linux-pm/aAplED3IA_J0eZN0@linaro.org/ Reported-by: Stephan Gerhold <stephan.gerhold@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Stephan Gerhold <stephan.gerhold@linaro.org> Reviewed-by: Lifeng Zheng <zhenglifeng1@huawei.com> Link: https://patch.msgid.link/5896780.DvuYhMxLoT@rjwysocki.net Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent 10e1498 commit 3f25e32

File tree

4 files changed

+73
-41
lines changed

4 files changed

+73
-41
lines changed

drivers/cpufreq/cpufreq.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,18 @@ void cpufreq_disable_fast_switch(struct cpufreq_policy *policy)
535535
EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch);
536536

537537
static unsigned int __resolve_freq(struct cpufreq_policy *policy,
538-
unsigned int target_freq, unsigned int relation)
538+
unsigned int target_freq,
539+
unsigned int min, unsigned int max,
540+
unsigned int relation)
539541
{
540542
unsigned int idx;
541543

544+
target_freq = clamp_val(target_freq, min, max);
545+
542546
if (!policy->freq_table)
543547
return target_freq;
544548

545-
idx = cpufreq_frequency_table_target(policy, target_freq, relation);
549+
idx = cpufreq_frequency_table_target(policy, target_freq, min, max, relation);
546550
policy->cached_resolved_idx = idx;
547551
policy->cached_target_freq = target_freq;
548552
return policy->freq_table[idx].frequency;
@@ -576,8 +580,7 @@ unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
576580
if (unlikely(min > max))
577581
min = max;
578582

579-
return __resolve_freq(policy, clamp_val(target_freq, min, max),
580-
CPUFREQ_RELATION_LE);
583+
return __resolve_freq(policy, target_freq, min, max, CPUFREQ_RELATION_LE);
581584
}
582585
EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
583586

@@ -2378,8 +2381,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
23782381
if (cpufreq_disabled())
23792382
return -ENODEV;
23802383

2381-
target_freq = clamp_val(target_freq, policy->min, policy->max);
2382-
target_freq = __resolve_freq(policy, target_freq, relation);
2384+
target_freq = __resolve_freq(policy, target_freq, policy->min,
2385+
policy->max, relation);
23832386

23842387
pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
23852388
policy->cpu, target_freq, relation, old_target_freq);
@@ -2708,8 +2711,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
27082711
* compiler optimizations around them because they may be accessed
27092712
* concurrently by cpufreq_driver_resolve_freq() during the update.
27102713
*/
2711-
WRITE_ONCE(policy->max, __resolve_freq(policy, new_data.max, CPUFREQ_RELATION_H));
2712-
new_data.min = __resolve_freq(policy, new_data.min, CPUFREQ_RELATION_L);
2714+
WRITE_ONCE(policy->max, __resolve_freq(policy, new_data.max,
2715+
new_data.min, new_data.max,
2716+
CPUFREQ_RELATION_H));
2717+
new_data.min = __resolve_freq(policy, new_data.min, new_data.min,
2718+
new_data.max, CPUFREQ_RELATION_L);
27132719
WRITE_ONCE(policy->min, new_data.min > policy->max ? policy->max : new_data.min);
27142720

27152721
trace_cpu_frequency_limits(policy);

drivers/cpufreq/cpufreq_ondemand.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
7777
return freq_next;
7878
}
7979

80-
index = cpufreq_frequency_table_target(policy, freq_next, relation);
80+
index = cpufreq_frequency_table_target(policy, freq_next, policy->min,
81+
policy->max, relation);
8182
freq_req = freq_table[index].frequency;
8283
freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
8384
freq_avg = freq_req - freq_reduc;

drivers/cpufreq/freq_table.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy)
115115
EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
116116

117117
int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
118-
unsigned int target_freq,
119-
unsigned int relation)
118+
unsigned int target_freq, unsigned int min,
119+
unsigned int max, unsigned int relation)
120120
{
121121
struct cpufreq_frequency_table optimal = {
122122
.driver_data = ~0,
@@ -147,7 +147,7 @@ int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
147147
cpufreq_for_each_valid_entry_idx(pos, table, i) {
148148
freq = pos->frequency;
149149

150-
if ((freq < policy->min) || (freq > policy->max))
150+
if (freq < min || freq > max)
151151
continue;
152152
if (freq == target_freq) {
153153
optimal.driver_data = i;

include/linux/cpufreq.h

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
812812
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy);
813813

814814
int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
815-
unsigned int target_freq,
816-
unsigned int relation);
815+
unsigned int target_freq, unsigned int min,
816+
unsigned int max, unsigned int relation);
817817
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
818818
unsigned int freq);
819819

@@ -877,12 +877,12 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
877877
return best;
878878
}
879879

880-
/* Works only on sorted freq-tables */
881-
static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
882-
unsigned int target_freq,
883-
bool efficiencies)
880+
static inline int find_index_l(struct cpufreq_policy *policy,
881+
unsigned int target_freq,
882+
unsigned int min, unsigned int max,
883+
bool efficiencies)
884884
{
885-
target_freq = clamp_val(target_freq, policy->min, policy->max);
885+
target_freq = clamp_val(target_freq, min, max);
886886

887887
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
888888
return cpufreq_table_find_index_al(policy, target_freq,
@@ -892,6 +892,14 @@ static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
892892
efficiencies);
893893
}
894894

895+
/* Works only on sorted freq-tables */
896+
static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
897+
unsigned int target_freq,
898+
bool efficiencies)
899+
{
900+
return find_index_l(policy, target_freq, policy->min, policy->max, efficiencies);
901+
}
902+
895903
/* Find highest freq at or below target in a table in ascending order */
896904
static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
897905
unsigned int target_freq,
@@ -945,12 +953,12 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
945953
return best;
946954
}
947955

948-
/* Works only on sorted freq-tables */
949-
static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
950-
unsigned int target_freq,
951-
bool efficiencies)
956+
static inline int find_index_h(struct cpufreq_policy *policy,
957+
unsigned int target_freq,
958+
unsigned int min, unsigned int max,
959+
bool efficiencies)
952960
{
953-
target_freq = clamp_val(target_freq, policy->min, policy->max);
961+
target_freq = clamp_val(target_freq, min, max);
954962

955963
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
956964
return cpufreq_table_find_index_ah(policy, target_freq,
@@ -960,6 +968,14 @@ static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
960968
efficiencies);
961969
}
962970

971+
/* Works only on sorted freq-tables */
972+
static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
973+
unsigned int target_freq,
974+
bool efficiencies)
975+
{
976+
return find_index_h(policy, target_freq, policy->min, policy->max, efficiencies);
977+
}
978+
963979
/* Find closest freq to target in a table in ascending order */
964980
static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
965981
unsigned int target_freq,
@@ -1030,12 +1046,12 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
10301046
return best;
10311047
}
10321048

1033-
/* Works only on sorted freq-tables */
1034-
static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
1035-
unsigned int target_freq,
1036-
bool efficiencies)
1049+
static inline int find_index_c(struct cpufreq_policy *policy,
1050+
unsigned int target_freq,
1051+
unsigned int min, unsigned int max,
1052+
bool efficiencies)
10371053
{
1038-
target_freq = clamp_val(target_freq, policy->min, policy->max);
1054+
target_freq = clamp_val(target_freq, min, max);
10391055

10401056
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
10411057
return cpufreq_table_find_index_ac(policy, target_freq,
@@ -1045,7 +1061,17 @@ static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
10451061
efficiencies);
10461062
}
10471063

1048-
static inline bool cpufreq_is_in_limits(struct cpufreq_policy *policy, int idx)
1064+
/* Works only on sorted freq-tables */
1065+
static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
1066+
unsigned int target_freq,
1067+
bool efficiencies)
1068+
{
1069+
return find_index_c(policy, target_freq, policy->min, policy->max, efficiencies);
1070+
}
1071+
1072+
static inline bool cpufreq_is_in_limits(struct cpufreq_policy *policy,
1073+
unsigned int min, unsigned int max,
1074+
int idx)
10491075
{
10501076
unsigned int freq;
10511077

@@ -1054,11 +1080,13 @@ static inline bool cpufreq_is_in_limits(struct cpufreq_policy *policy, int idx)
10541080

10551081
freq = policy->freq_table[idx].frequency;
10561082

1057-
return freq == clamp_val(freq, policy->min, policy->max);
1083+
return freq == clamp_val(freq, min, max);
10581084
}
10591085

10601086
static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
10611087
unsigned int target_freq,
1088+
unsigned int min,
1089+
unsigned int max,
10621090
unsigned int relation)
10631091
{
10641092
bool efficiencies = policy->efficiencies_available &&
@@ -1069,29 +1097,26 @@ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
10691097
relation &= ~CPUFREQ_RELATION_E;
10701098

10711099
if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED))
1072-
return cpufreq_table_index_unsorted(policy, target_freq,
1073-
relation);
1100+
return cpufreq_table_index_unsorted(policy, target_freq, min,
1101+
max, relation);
10741102
retry:
10751103
switch (relation) {
10761104
case CPUFREQ_RELATION_L:
1077-
idx = cpufreq_table_find_index_l(policy, target_freq,
1078-
efficiencies);
1105+
idx = find_index_l(policy, target_freq, min, max, efficiencies);
10791106
break;
10801107
case CPUFREQ_RELATION_H:
1081-
idx = cpufreq_table_find_index_h(policy, target_freq,
1082-
efficiencies);
1108+
idx = find_index_h(policy, target_freq, min, max, efficiencies);
10831109
break;
10841110
case CPUFREQ_RELATION_C:
1085-
idx = cpufreq_table_find_index_c(policy, target_freq,
1086-
efficiencies);
1111+
idx = find_index_c(policy, target_freq, min, max, efficiencies);
10871112
break;
10881113
default:
10891114
WARN_ON_ONCE(1);
10901115
return 0;
10911116
}
10921117

1093-
/* Limit frequency index to honor policy->min/max */
1094-
if (!cpufreq_is_in_limits(policy, idx) && efficiencies) {
1118+
/* Limit frequency index to honor min and max */
1119+
if (!cpufreq_is_in_limits(policy, min, max, idx) && efficiencies) {
10951120
efficiencies = false;
10961121
goto retry;
10971122
}

0 commit comments

Comments
 (0)