Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <vincent.donnefort@arm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Vincent Donnefort and committed by
Rafael J. Wysocki
1f39fa0d 442d24a5

+106 -33
+2 -1
drivers/cpufreq/acpi-cpufreq.c
··· 470 470 if (policy->cached_target_freq == target_freq) 471 471 index = policy->cached_resolved_idx; 472 472 else 473 - index = cpufreq_table_find_index_dl(policy, target_freq); 473 + index = cpufreq_table_find_index_dl(policy, target_freq, 474 + false); 474 475 475 476 entry = &policy->freq_table[index]; 476 477 next_freq = entry->frequency;
+2 -1
drivers/cpufreq/amd_freq_sensitivity.c
··· 91 91 unsigned int index; 92 92 93 93 index = cpufreq_table_find_index_h(policy, 94 - policy->cur - 1); 94 + policy->cur - 1, 95 + relation & CPUFREQ_RELATION_E); 95 96 freq_next = policy->freq_table[index].frequency; 96 97 } 97 98
+9 -1
drivers/cpufreq/cpufreq.c
··· 2260 2260 !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS)) 2261 2261 return 0; 2262 2262 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 + 2264 2271 return cpufreq_driver->target(policy, target_freq, relation); 2272 + } 2265 2273 2266 2274 if (!cpufreq_driver->target_index) 2267 2275 return -EINVAL;
+4 -2
drivers/cpufreq/cpufreq_ondemand.c
··· 83 83 freq_avg = freq_req - freq_reduc; 84 84 85 85 /* 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); 87 88 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); 89 91 freq_hi = freq_table[index].frequency; 90 92 91 93 /* Find out how long we have to be in hi and lo freqs */
+2 -2
drivers/cpufreq/powernv-cpufreq.c
··· 934 934 policy = cpufreq_cpu_get(cpu); 935 935 if (!policy) 936 936 continue; 937 - index = cpufreq_table_find_index_c(policy, policy->cur); 937 + index = cpufreq_table_find_index_c(policy, policy->cur, false); 938 938 powernv_cpufreq_target_index(policy, index); 939 939 cpumask_andnot(&mask, &mask, policy->cpus); 940 940 cpufreq_cpu_put(policy); ··· 1022 1022 int index; 1023 1023 struct powernv_smp_call_data freq_data; 1024 1024 1025 - index = cpufreq_table_find_index_dl(policy, target_freq); 1025 + index = cpufreq_table_find_index_dl(policy, target_freq, false); 1026 1026 freq_data.pstate_id = powernv_freqs[index].driver_data; 1027 1027 freq_data.gpstate_id = powernv_freqs[index].driver_data; 1028 1028 set_pstate(&freq_data);
+1 -1
drivers/cpufreq/s5pv210-cpufreq.c
··· 243 243 new_freq = s5pv210_freq_table[index].frequency; 244 244 245 245 /* 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); 247 247 248 248 arm_volt = dvs_conf[index].arm_volt; 249 249 int_volt = dvs_conf[index].int_volt;
+86 -25
include/linux/cpufreq.h
··· 119 119 bool strict_target; 120 120 121 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 + 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 124 131 * scaling driver (0, which is the default, means no preference). ··· 280 273 #define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ 281 274 #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ 282 275 #define CPUFREQ_RELATION_C 2 /* closest frequency to target */ 276 + /* relation flags */ 277 + #define CPUFREQ_RELATION_E BIT(2) /* Get if possible an efficient frequency */ 283 278 284 279 struct freq_attr { 285 280 struct attribute attr; ··· 750 741 continue; \ 751 742 else 752 743 744 + /** 745 + * cpufreq_for_each_efficient_entry_idx - iterate with index over a cpufreq 746 + * frequency_table excluding CPUFREQ_ENTRY_INVALID and 747 + * CPUFREQ_INEFFICIENT_FREQ frequencies. 748 + * @pos: the &struct cpufreq_frequency_table to use as a loop cursor. 749 + * @table: the &struct cpufreq_frequency_table to iterate over. 750 + * @idx: the table entry currently being processed. 751 + * @efficiencies: set to true to only iterate over efficient frequencies. 752 + */ 753 + 754 + #define cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) \ 755 + cpufreq_for_each_valid_entry_idx(pos, table, idx) \ 756 + if (efficiencies && (pos->flags & CPUFREQ_INEFFICIENT_FREQ)) \ 757 + continue; \ 758 + else 759 + 753 760 754 761 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 755 762 struct cpufreq_frequency_table *table); ··· 790 765 791 766 /* Find lowest freq at or above target in a table in ascending order */ 792 767 static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy, 793 - unsigned int target_freq) 768 + unsigned int target_freq, 769 + bool efficiencies) 794 770 { 795 771 struct cpufreq_frequency_table *table = policy->freq_table; 796 772 struct cpufreq_frequency_table *pos; 797 773 unsigned int freq; 798 774 int idx, best = -1; 799 775 800 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 776 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 801 777 freq = pos->frequency; 802 778 803 779 if (freq >= target_freq) ··· 812 786 813 787 /* Find lowest freq at or above target in a table in descending order */ 814 788 static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy, 815 - unsigned int target_freq) 789 + unsigned int target_freq, 790 + bool efficiencies) 816 791 { 817 792 struct cpufreq_frequency_table *table = policy->freq_table; 818 793 struct cpufreq_frequency_table *pos; 819 794 unsigned int freq; 820 795 int idx, best = -1; 821 796 822 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 797 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 823 798 freq = pos->frequency; 824 799 825 800 if (freq == target_freq) ··· 843 816 844 817 /* Works only on sorted freq-tables */ 845 818 static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy, 846 - unsigned int target_freq) 819 + unsigned int target_freq, 820 + bool efficiencies) 847 821 { 848 822 target_freq = clamp_val(target_freq, policy->min, policy->max); 849 823 850 824 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING) 851 - return cpufreq_table_find_index_al(policy, target_freq); 825 + return cpufreq_table_find_index_al(policy, target_freq, 826 + efficiencies); 852 827 else 853 - return cpufreq_table_find_index_dl(policy, target_freq); 828 + return cpufreq_table_find_index_dl(policy, target_freq, 829 + efficiencies); 854 830 } 855 831 856 832 /* Find highest freq at or below target in a table in ascending order */ 857 833 static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy, 858 - unsigned int target_freq) 834 + unsigned int target_freq, 835 + bool efficiencies) 859 836 { 860 837 struct cpufreq_frequency_table *table = policy->freq_table; 861 838 struct cpufreq_frequency_table *pos; 862 839 unsigned int freq; 863 840 int idx, best = -1; 864 841 865 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 842 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 866 843 freq = pos->frequency; 867 844 868 845 if (freq == target_freq) ··· 889 858 890 859 /* Find highest freq at or below target in a table in descending order */ 891 860 static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy, 892 - unsigned int target_freq) 861 + unsigned int target_freq, 862 + bool efficiencies) 893 863 { 894 864 struct cpufreq_frequency_table *table = policy->freq_table; 895 865 struct cpufreq_frequency_table *pos; 896 866 unsigned int freq; 897 867 int idx, best = -1; 898 868 899 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 869 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 900 870 freq = pos->frequency; 901 871 902 872 if (freq <= target_freq) ··· 911 879 912 880 /* Works only on sorted freq-tables */ 913 881 static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy, 914 - unsigned int target_freq) 882 + unsigned int target_freq, 883 + bool efficiencies) 915 884 { 916 885 target_freq = clamp_val(target_freq, policy->min, policy->max); 917 886 918 887 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING) 919 - return cpufreq_table_find_index_ah(policy, target_freq); 888 + return cpufreq_table_find_index_ah(policy, target_freq, 889 + efficiencies); 920 890 else 921 - return cpufreq_table_find_index_dh(policy, target_freq); 891 + return cpufreq_table_find_index_dh(policy, target_freq, 892 + efficiencies); 922 893 } 923 894 924 895 /* Find closest freq to target in a table in ascending order */ 925 896 static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy, 926 - unsigned int target_freq) 897 + unsigned int target_freq, 898 + bool efficiencies) 927 899 { 928 900 struct cpufreq_frequency_table *table = policy->freq_table; 929 901 struct cpufreq_frequency_table *pos; 930 902 unsigned int freq; 931 903 int idx, best = -1; 932 904 933 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 905 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 934 906 freq = pos->frequency; 935 907 936 908 if (freq == target_freq) ··· 961 925 962 926 /* Find closest freq to target in a table in descending order */ 963 927 static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy, 964 - unsigned int target_freq) 928 + unsigned int target_freq, 929 + bool efficiencies) 965 930 { 966 931 struct cpufreq_frequency_table *table = policy->freq_table; 967 932 struct cpufreq_frequency_table *pos; 968 933 unsigned int freq; 969 934 int idx, best = -1; 970 935 971 - cpufreq_for_each_valid_entry_idx(pos, table, idx) { 936 + cpufreq_for_each_efficient_entry_idx(pos, table, idx, efficiencies) { 972 937 freq = pos->frequency; 973 938 974 939 if (freq == target_freq) ··· 996 959 997 960 /* Works only on sorted freq-tables */ 998 961 static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy, 999 - unsigned int target_freq) 962 + unsigned int target_freq, 963 + bool efficiencies) 1000 964 { 1001 965 target_freq = clamp_val(target_freq, policy->min, policy->max); 1002 966 1003 967 if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING) 1004 - return cpufreq_table_find_index_ac(policy, target_freq); 968 + return cpufreq_table_find_index_ac(policy, target_freq, 969 + efficiencies); 1005 970 else 1006 - return cpufreq_table_find_index_dc(policy, target_freq); 971 + return cpufreq_table_find_index_dc(policy, target_freq, 972 + efficiencies); 1007 973 } 1008 974 1009 975 static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 1010 976 unsigned int target_freq, 1011 977 unsigned int relation) 1012 978 { 979 + bool efficiencies = policy->efficiencies_available && 980 + (relation & CPUFREQ_RELATION_E); 981 + int idx; 982 + 983 + /* cpufreq_table_index_unsorted() has no use for this flag anyway */ 984 + relation &= ~CPUFREQ_RELATION_E; 985 + 1013 986 if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED)) 1014 987 return cpufreq_table_index_unsorted(policy, target_freq, 1015 988 relation); 1016 - 989 + retry: 1017 990 switch (relation) { 1018 991 case CPUFREQ_RELATION_L: 1019 - return cpufreq_table_find_index_l(policy, target_freq); 992 + idx = cpufreq_table_find_index_l(policy, target_freq, 993 + efficiencies); 994 + break; 1020 995 case CPUFREQ_RELATION_H: 1021 - return cpufreq_table_find_index_h(policy, target_freq); 996 + idx = cpufreq_table_find_index_h(policy, target_freq, 997 + efficiencies); 998 + break; 1022 999 case CPUFREQ_RELATION_C: 1023 - return cpufreq_table_find_index_c(policy, target_freq); 1000 + idx = cpufreq_table_find_index_c(policy, target_freq, 1001 + efficiencies); 1002 + break; 1024 1003 default: 1025 1004 WARN_ON_ONCE(1); 1026 1005 return 0; 1027 1006 } 1007 + 1008 + if (idx < 0 && efficiencies) { 1009 + efficiencies = false; 1010 + goto retry; 1011 + } 1012 + 1013 + return idx; 1028 1014 } 1029 1015 1030 1016 static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy *policy) ··· 1087 1027 cpufreq_for_each_valid_entry(pos, policy->freq_table) { 1088 1028 if (pos->frequency == frequency) { 1089 1029 pos->flags |= CPUFREQ_INEFFICIENT_FREQ; 1030 + policy->efficiencies_available = true; 1090 1031 return 0; 1091 1032 } 1092 1033 }