Skip to content

Commit 1f39fa0

Browse files
Vincent Donnefortrafaeljw
authored andcommitted
cpufreq: Introducing CPUFREQ_RELATION_E
This newly introduced flag can be applied by a governor to a CPUFreq relation, when looking for a frequency within the policy table. The resolution would then only walk through efficient frequencies. Even with the flag set, the policy max limit will still be honoured. If no efficient frequencies can be found within the limits of the policy, an inefficient one would be returned. Signed-off-by: Vincent Donnefort <[email protected]> Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 442d24a commit 1f39fa0

File tree

7 files changed

+106
-33
lines changed

7 files changed

+106
-33
lines changed

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,8 @@ static unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
470470
if (policy->cached_target_freq == target_freq)
471471
index = policy->cached_resolved_idx;
472472
else
473-
index = cpufreq_table_find_index_dl(policy, target_freq);
473+
index = cpufreq_table_find_index_dl(policy, target_freq,
474+
false);
474475

475476
entry = &policy->freq_table[index];
476477
next_freq = entry->frequency;

drivers/cpufreq/amd_freq_sensitivity.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
9191
unsigned int index;
9292

9393
index = cpufreq_table_find_index_h(policy,
94-
policy->cur - 1);
94+
policy->cur - 1,
95+
relation & CPUFREQ_RELATION_E);
9596
freq_next = policy->freq_table[index].frequency;
9697
}
9798

drivers/cpufreq/cpufreq.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2260,8 +2260,16 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
22602260
!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
22612261
return 0;
22622262

2263-
if (cpufreq_driver->target)
2263+
if (cpufreq_driver->target) {
2264+
/*
2265+
* If the driver hasn't setup a single inefficient frequency,
2266+
* it's unlikely it knows how to decode CPUFREQ_RELATION_E.
2267+
*/
2268+
if (!policy->efficiencies_available)
2269+
relation &= ~CPUFREQ_RELATION_E;
2270+
22642271
return cpufreq_driver->target(policy, target_freq, relation);
2272+
}
22652273

22662274
if (!cpufreq_driver->target_index)
22672275
return -EINVAL;

drivers/cpufreq/cpufreq_ondemand.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
8383
freq_avg = freq_req - freq_reduc;
8484

8585
/* Find freq bounds for freq_avg in freq_table */
86-
index = cpufreq_table_find_index_h(policy, freq_avg);
86+
index = cpufreq_table_find_index_h(policy, freq_avg,
87+
relation & CPUFREQ_RELATION_E);
8788
freq_lo = freq_table[index].frequency;
88-
index = cpufreq_table_find_index_l(policy, freq_avg);
89+
index = cpufreq_table_find_index_l(policy, freq_avg,
90+
relation & CPUFREQ_RELATION_E);
8991
freq_hi = freq_table[index].frequency;
9092

9193
/* Find out how long we have to be in hi and lo freqs */

drivers/cpufreq/powernv-cpufreq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ static void powernv_cpufreq_work_fn(struct work_struct *work)
934934
policy = cpufreq_cpu_get(cpu);
935935
if (!policy)
936936
continue;
937-
index = cpufreq_table_find_index_c(policy, policy->cur);
937+
index = cpufreq_table_find_index_c(policy, policy->cur, false);
938938
powernv_cpufreq_target_index(policy, index);
939939
cpumask_andnot(&mask, &mask, policy->cpus);
940940
cpufreq_cpu_put(policy);
@@ -1022,7 +1022,7 @@ static unsigned int powernv_fast_switch(struct cpufreq_policy *policy,
10221022
int index;
10231023
struct powernv_smp_call_data freq_data;
10241024

1025-
index = cpufreq_table_find_index_dl(policy, target_freq);
1025+
index = cpufreq_table_find_index_dl(policy, target_freq, false);
10261026
freq_data.pstate_id = powernv_freqs[index].driver_data;
10271027
freq_data.gpstate_id = powernv_freqs[index].driver_data;
10281028
set_pstate(&freq_data);

drivers/cpufreq/s5pv210-cpufreq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
243243
new_freq = s5pv210_freq_table[index].frequency;
244244

245245
/* Finding current running level index */
246-
priv_index = cpufreq_table_find_index_h(policy, old_freq);
246+
priv_index = cpufreq_table_find_index_h(policy, old_freq, false);
247247

248248
arm_volt = dvs_conf[index].arm_volt;
249249
int_volt = dvs_conf[index].int_volt;

include/linux/cpufreq.h

Lines changed: 86 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ struct cpufreq_policy {
118118
*/
119119
bool strict_target;
120120

121+
/*
122+
* Set if inefficient frequencies were found in the frequency table.
123+
* This indicates if the relation flag CPUFREQ_RELATION_E can be
124+
* honored.
125+
*/
126+
bool efficiencies_available;
127+
121128
/*
122129
* Preferred average time interval between consecutive invocations of
123130
* the driver to set the frequency for this policy. To be set by the
@@ -273,6 +280,8 @@ static inline void cpufreq_stats_record_transition(struct cpufreq_policy *policy
273280
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */
274281
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */
275282
#define CPUFREQ_RELATION_C 2 /* closest frequency to target */
283+
/* relation flags */
284+
#define CPUFREQ_RELATION_E BIT(2) /* Get if possible an efficient frequency */
276285

277286
struct freq_attr {
278287
struct attribute attr;
@@ -741,6 +750,22 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev,
741750
continue; \
742751
else
743752

753+
/**
754+
* cpufreq_for_each_efficient_entry_idx - iterate with index over a cpufreq
755+
* frequency_table excluding CPUFREQ_ENTRY_INVALID and
756+
* CPUFREQ_INEFFICIENT_FREQ frequencies.
757+
* @pos: the &struct cpufreq_frequency_table to use as a loop cursor.
758+
* @table: the &struct cpufreq_frequency_table to iterate over.
759+
* @idx: the table entry currently being processed.
760+
* @efficiencies: set to true to only iterate over efficient frequencies.
761+
*/
762+
763+
#define cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) \
764+
cpufreq_for_each_valid_entry_idx(pos, table, idx) \
765+
if (efficiencies && (pos->flags & CPUFREQ_INEFFICIENT_FREQ)) \
766+
continue; \
767+
else
768+
744769

745770
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
746771
struct cpufreq_frequency_table *table);
@@ -765,14 +790,15 @@ bool policy_has_boost_freq(struct cpufreq_policy *policy);
765790

766791
/* Find lowest freq at or above target in a table in ascending order */
767792
static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
768-
unsigned int target_freq)
793+
unsigned int target_freq,
794+
bool efficiencies)
769795
{
770796
struct cpufreq_frequency_table *table = policy->freq_table;
771797
struct cpufreq_frequency_table *pos;
772798
unsigned int freq;
773799
int idx, best = -1;
774800

775-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
801+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
776802
freq = pos->frequency;
777803

778804
if (freq >= target_freq)
@@ -786,14 +812,15 @@ static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
786812

787813
/* Find lowest freq at or above target in a table in descending order */
788814
static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
789-
unsigned int target_freq)
815+
unsigned int target_freq,
816+
bool efficiencies)
790817
{
791818
struct cpufreq_frequency_table *table = policy->freq_table;
792819
struct cpufreq_frequency_table *pos;
793820
unsigned int freq;
794821
int idx, best = -1;
795822

796-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
823+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
797824
freq = pos->frequency;
798825

799826
if (freq == target_freq)
@@ -816,26 +843,30 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
816843

817844
/* Works only on sorted freq-tables */
818845
static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
819-
unsigned int target_freq)
846+
unsigned int target_freq,
847+
bool efficiencies)
820848
{
821849
target_freq = clamp_val(target_freq, policy->min, policy->max);
822850

823851
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
824-
return cpufreq_table_find_index_al(policy, target_freq);
852+
return cpufreq_table_find_index_al(policy, target_freq,
853+
efficiencies);
825854
else
826-
return cpufreq_table_find_index_dl(policy, target_freq);
855+
return cpufreq_table_find_index_dl(policy, target_freq,
856+
efficiencies);
827857
}
828858

829859
/* Find highest freq at or below target in a table in ascending order */
830860
static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
831-
unsigned int target_freq)
861+
unsigned int target_freq,
862+
bool efficiencies)
832863
{
833864
struct cpufreq_frequency_table *table = policy->freq_table;
834865
struct cpufreq_frequency_table *pos;
835866
unsigned int freq;
836867
int idx, best = -1;
837868

838-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
869+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
839870
freq = pos->frequency;
840871

841872
if (freq == target_freq)
@@ -858,14 +889,15 @@ static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
858889

859890
/* Find highest freq at or below target in a table in descending order */
860891
static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
861-
unsigned int target_freq)
892+
unsigned int target_freq,
893+
bool efficiencies)
862894
{
863895
struct cpufreq_frequency_table *table = policy->freq_table;
864896
struct cpufreq_frequency_table *pos;
865897
unsigned int freq;
866898
int idx, best = -1;
867899

868-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
900+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
869901
freq = pos->frequency;
870902

871903
if (freq <= target_freq)
@@ -879,26 +911,30 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
879911

880912
/* Works only on sorted freq-tables */
881913
static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
882-
unsigned int target_freq)
914+
unsigned int target_freq,
915+
bool efficiencies)
883916
{
884917
target_freq = clamp_val(target_freq, policy->min, policy->max);
885918

886919
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
887-
return cpufreq_table_find_index_ah(policy, target_freq);
920+
return cpufreq_table_find_index_ah(policy, target_freq,
921+
efficiencies);
888922
else
889-
return cpufreq_table_find_index_dh(policy, target_freq);
923+
return cpufreq_table_find_index_dh(policy, target_freq,
924+
efficiencies);
890925
}
891926

892927
/* Find closest freq to target in a table in ascending order */
893928
static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
894-
unsigned int target_freq)
929+
unsigned int target_freq,
930+
bool efficiencies)
895931
{
896932
struct cpufreq_frequency_table *table = policy->freq_table;
897933
struct cpufreq_frequency_table *pos;
898934
unsigned int freq;
899935
int idx, best = -1;
900936

901-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
937+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
902938
freq = pos->frequency;
903939

904940
if (freq == target_freq)
@@ -925,14 +961,15 @@ static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
925961

926962
/* Find closest freq to target in a table in descending order */
927963
static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
928-
unsigned int target_freq)
964+
unsigned int target_freq,
965+
bool efficiencies)
929966
{
930967
struct cpufreq_frequency_table *table = policy->freq_table;
931968
struct cpufreq_frequency_table *pos;
932969
unsigned int freq;
933970
int idx, best = -1;
934971

935-
cpufreq_for_each_valid_entry_idx(pos, table, idx) {
972+
cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) {
936973
freq = pos->frequency;
937974

938975
if (freq == target_freq)
@@ -959,35 +996,58 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
959996

960997
/* Works only on sorted freq-tables */
961998
static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
962-
unsigned int target_freq)
999+
unsigned int target_freq,
1000+
bool efficiencies)
9631001
{
9641002
target_freq = clamp_val(target_freq, policy->min, policy->max);
9651003

9661004
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
967-
return cpufreq_table_find_index_ac(policy, target_freq);
1005+
return cpufreq_table_find_index_ac(policy, target_freq,
1006+
efficiencies);
9681007
else
969-
return cpufreq_table_find_index_dc(policy, target_freq);
1008+
return cpufreq_table_find_index_dc(policy, target_freq,
1009+
efficiencies);
9701010
}
9711011

9721012
static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
9731013
unsigned int target_freq,
9741014
unsigned int relation)
9751015
{
1016+
bool efficiencies = policy->efficiencies_available &&
1017+
(relation & CPUFREQ_RELATION_E);
1018+
int idx;
1019+
1020+
/* cpufreq_table_index_unsorted() has no use for this flag anyway */
1021+
relation &= ~CPUFREQ_RELATION_E;
1022+
9761023
if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED))
9771024
return cpufreq_table_index_unsorted(policy, target_freq,
9781025
relation);
979-
1026+
retry:
9801027
switch (relation) {
9811028
case CPUFREQ_RELATION_L:
982-
return cpufreq_table_find_index_l(policy, target_freq);
1029+
idx = cpufreq_table_find_index_l(policy, target_freq,
1030+
efficiencies);
1031+
break;
9831032
case CPUFREQ_RELATION_H:
984-
return cpufreq_table_find_index_h(policy, target_freq);
1033+
idx = cpufreq_table_find_index_h(policy, target_freq,
1034+
efficiencies);
1035+
break;
9851036
case CPUFREQ_RELATION_C:
986-
return cpufreq_table_find_index_c(policy, target_freq);
1037+
idx = cpufreq_table_find_index_c(policy, target_freq,
1038+
efficiencies);
1039+
break;
9871040
default:
9881041
WARN_ON_ONCE(1);
9891042
return 0;
9901043
}
1044+
1045+
if (idx < 0 && efficiencies) {
1046+
efficiencies = false;
1047+
goto retry;
1048+
}
1049+
1050+
return idx;
9911051
}
9921052

9931053
static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy *policy)
@@ -1027,6 +1087,7 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy,
10271087
cpufreq_for_each_valid_entry(pos, policy->freq_table) {
10281088
if (pos->frequency == frequency) {
10291089
pos->flags |= CPUFREQ_INEFFICIENT_FREQ;
1090+
policy->efficiencies_available = true;
10301091
return 0;
10311092
}
10321093
}

0 commit comments

Comments
 (0)