@@ -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
277286struct 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
745770int 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 */
767792static 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 */
788814static 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 */
818845static 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 */
830860static 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 */
860891static 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 */
881913static 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 */
893928static 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 */
927963static 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 */
961998static 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
9721012static 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
9931053static 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