@@ -118,6 +118,13 @@ struct cpufreq_policy {
118
118
*/
119
119
bool strict_target ;
120
120
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
+
121
128
/*
122
129
* Preferred average time interval between consecutive invocations of
123
130
* 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
273
280
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */
274
281
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */
275
282
#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 */
276
285
277
286
struct freq_attr {
278
287
struct attribute attr ;
@@ -741,6 +750,22 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev,
741
750
continue; \
742
751
else
743
752
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
+
744
769
745
770
int cpufreq_frequency_table_cpuinfo (struct cpufreq_policy * policy ,
746
771
struct cpufreq_frequency_table * table );
@@ -765,14 +790,15 @@ bool policy_has_boost_freq(struct cpufreq_policy *policy);
765
790
766
791
/* Find lowest freq at or above target in a table in ascending order */
767
792
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 )
769
795
{
770
796
struct cpufreq_frequency_table * table = policy -> freq_table ;
771
797
struct cpufreq_frequency_table * pos ;
772
798
unsigned int freq ;
773
799
int idx , best = -1 ;
774
800
775
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
801
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
776
802
freq = pos -> frequency ;
777
803
778
804
if (freq >= target_freq )
@@ -786,14 +812,15 @@ static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
786
812
787
813
/* Find lowest freq at or above target in a table in descending order */
788
814
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 )
790
817
{
791
818
struct cpufreq_frequency_table * table = policy -> freq_table ;
792
819
struct cpufreq_frequency_table * pos ;
793
820
unsigned int freq ;
794
821
int idx , best = -1 ;
795
822
796
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
823
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
797
824
freq = pos -> frequency ;
798
825
799
826
if (freq == target_freq )
@@ -816,26 +843,30 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
816
843
817
844
/* Works only on sorted freq-tables */
818
845
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 )
820
848
{
821
849
target_freq = clamp_val (target_freq , policy -> min , policy -> max );
822
850
823
851
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 );
825
854
else
826
- return cpufreq_table_find_index_dl (policy , target_freq );
855
+ return cpufreq_table_find_index_dl (policy , target_freq ,
856
+ efficiencies );
827
857
}
828
858
829
859
/* Find highest freq at or below target in a table in ascending order */
830
860
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 )
832
863
{
833
864
struct cpufreq_frequency_table * table = policy -> freq_table ;
834
865
struct cpufreq_frequency_table * pos ;
835
866
unsigned int freq ;
836
867
int idx , best = -1 ;
837
868
838
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
869
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
839
870
freq = pos -> frequency ;
840
871
841
872
if (freq == target_freq )
@@ -858,14 +889,15 @@ static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
858
889
859
890
/* Find highest freq at or below target in a table in descending order */
860
891
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 )
862
894
{
863
895
struct cpufreq_frequency_table * table = policy -> freq_table ;
864
896
struct cpufreq_frequency_table * pos ;
865
897
unsigned int freq ;
866
898
int idx , best = -1 ;
867
899
868
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
900
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
869
901
freq = pos -> frequency ;
870
902
871
903
if (freq <= target_freq )
@@ -879,26 +911,30 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
879
911
880
912
/* Works only on sorted freq-tables */
881
913
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 )
883
916
{
884
917
target_freq = clamp_val (target_freq , policy -> min , policy -> max );
885
918
886
919
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 );
888
922
else
889
- return cpufreq_table_find_index_dh (policy , target_freq );
923
+ return cpufreq_table_find_index_dh (policy , target_freq ,
924
+ efficiencies );
890
925
}
891
926
892
927
/* Find closest freq to target in a table in ascending order */
893
928
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 )
895
931
{
896
932
struct cpufreq_frequency_table * table = policy -> freq_table ;
897
933
struct cpufreq_frequency_table * pos ;
898
934
unsigned int freq ;
899
935
int idx , best = -1 ;
900
936
901
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
937
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
902
938
freq = pos -> frequency ;
903
939
904
940
if (freq == target_freq )
@@ -925,14 +961,15 @@ static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
925
961
926
962
/* Find closest freq to target in a table in descending order */
927
963
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 )
929
966
{
930
967
struct cpufreq_frequency_table * table = policy -> freq_table ;
931
968
struct cpufreq_frequency_table * pos ;
932
969
unsigned int freq ;
933
970
int idx , best = -1 ;
934
971
935
- cpufreq_for_each_valid_entry_idx (pos , table , idx ) {
972
+ cpufreq_for_each_efficient_entry_idx (pos , table , idx , efficiencies ) {
936
973
freq = pos -> frequency ;
937
974
938
975
if (freq == target_freq )
@@ -959,35 +996,58 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
959
996
960
997
/* Works only on sorted freq-tables */
961
998
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 )
963
1001
{
964
1002
target_freq = clamp_val (target_freq , policy -> min , policy -> max );
965
1003
966
1004
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 );
968
1007
else
969
- return cpufreq_table_find_index_dc (policy , target_freq );
1008
+ return cpufreq_table_find_index_dc (policy , target_freq ,
1009
+ efficiencies );
970
1010
}
971
1011
972
1012
static inline int cpufreq_frequency_table_target (struct cpufreq_policy * policy ,
973
1013
unsigned int target_freq ,
974
1014
unsigned int relation )
975
1015
{
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
+
976
1023
if (unlikely (policy -> freq_table_sorted == CPUFREQ_TABLE_UNSORTED ))
977
1024
return cpufreq_table_index_unsorted (policy , target_freq ,
978
1025
relation );
979
-
1026
+ retry :
980
1027
switch (relation ) {
981
1028
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 ;
983
1032
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 ;
985
1036
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 ;
987
1040
default :
988
1041
WARN_ON_ONCE (1 );
989
1042
return 0 ;
990
1043
}
1044
+
1045
+ if (idx < 0 && efficiencies ) {
1046
+ efficiencies = false;
1047
+ goto retry ;
1048
+ }
1049
+
1050
+ return idx ;
991
1051
}
992
1052
993
1053
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,
1027
1087
cpufreq_for_each_valid_entry (pos , policy -> freq_table ) {
1028
1088
if (pos -> frequency == frequency ) {
1029
1089
pos -> flags |= CPUFREQ_INEFFICIENT_FREQ ;
1090
+ policy -> efficiencies_available = true;
1030
1091
return 0 ;
1031
1092
}
1032
1093
}
0 commit comments