我们再来看看powersave的实现,如下所示event是CPUFREQ_GOV_START时,即开始这个governer时直接调用__cpufreq_driver_target来设定最低频率。
19 static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
20 unsigned int event)
21 {
22 switch (event) {
23 case CPUFREQ_GOV_START:
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->min, event);
27 __cpufreq_driver_target(policy, policy->min,
28 CPUFREQ_RELATION_L);
29 break;
30 default:
31 break;
32 }
33 return 0;
34 }
performance 正好相反
19 static int cpufreq_governor_performance(struct cpufreq_policy *policy,
20 unsigned int event)
21 {
22 switch (event) {
23 case CPUFREQ_GOV_START:
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->max, event);
27 __cpufreq_driver_target(policy, policy->max,
28 CPUFREQ_RELATION_H);
29 break;
30 default:
31 break;
32 }
33 return 0;
34 }
也是直接调用__cpufreq_driver_target 以最大频率运行.
我们看看__cpufreq_driver_target的实现。
可见cpufreq driver设定freq有两种方式
第一种:
如果driver实现了target,则直接调用target设定hw寄存器的频率.
1953 if (cpufreq_driver->target)
1954 return cpufreq_driver->target(policy, target_freq, relation);
第二种是:必须实现cpufreq_driver->target_index方法.
先得到freq 表
1959 freq_table = cpufreq_frequency_get_table(policy->cpu);
调用cpufreq_frequency_table_target 根据relation是CPUFREQ_RELATION_H 或者 CPUFREQ_RELATION_L的得到最大或最小频率.
1965 retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
1966 relation, &index);
调用__target_index 设定频率.
1921 int __cpufreq_driver_target(struct cpufreq_policy *policy,
1922 unsigned int target_freq,
1923 unsigned int relation)
1924 {
1925 unsigned int old_target_freq = target_freq;
1926 struct cpufreq_frequency_table *freq_table;
1927 int index, retval;
1928
1929 if (cpufreq_disabled())
1930 return -ENODEV;
1931
1932 /* Make sure that target_freq is within supported range */
1933 if (target_freq > policy->max)
1934 target_freq = policy->max;
1935 if (target_freq < policy->min)
1936 target_freq = policy->min;
1937
1938 pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
1939 policy->cpu, target_freq, relation, old_target_freq);
1940
1941 /*
1942 * This might look like a redundant call as we are checking it again
1943 * after finding index. But it is left intentionally for cases where
1944 * exactly same freq is called again and so we can save on few function
1945 * calls.
1946 */
1947 if (target_freq == policy->cur)
1948 return 0;
1949
1950 /* Save last value to restore later on errors */
1951 policy->restore_freq = policy->cur;
1952
1953 if (cpufreq_driver->target)
1954 return cpufreq_driver->target(policy, target_freq, relation);
1955
1956 if (!cpufreq_driver->target_index)
1957 return -EINVAL;
1958
1959 freq_table = cpufreq_frequency_get_table(policy->cpu);
1960 if (unlikely(!freq_table)) {
1961 pr_err("%s: Unable to find freq_table\n", __func__);
1962 return -EINVAL;
1963 }
1964
1965 retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
1966 relation, &index);
1967 if (unlikely(retval)) {
1968 pr_err("%s: Unable to find matching freq\n", __func__);
1969 return retval;
1970 }
1971
1972 if (freq_table[index].frequency == policy->cur)
1973 return 0;
1974
1975 return __target_index(policy, freq_table, index);
1976 }
1977 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
__target_index 会根据cpufreq_driver->flags 来判断是修改freq是同步还是异步操作,如果是异步就直接调用
cpufreq_driver->target_index 设定频率,如果是同步就要调用cpufreq_freq_transition_begin和cpufreq_freq_transition_end 做一些包含.
1867 static int __target_index(struct cpufreq_policy *policy,
1868 struct cpufreq_frequency_table *freq_table, int index)
1869 {
1870 struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0};
1871 unsigned int intermediate_freq = 0;
1872 int retval = -EINVAL;
1873 bool notify;
1874
1875 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
1876 if (notify) {
1877 /* Handle switching to intermediate frequency */
1878 if (cpufreq_driver->get_intermediate) {
1879 retval = __target_intermediate(policy, &freqs, index);
1880 if (retval)
1881 return retval;
1882
1883 intermediate_freq = freqs.new;
1884 /* Set old freq to intermediate */
1885 if (intermediate_freq)
1886 freqs.old = freqs.new;
1887 }
1888
1889 freqs.new = freq_table[index].frequency;
1890 pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
1891 __func__, policy->cpu, freqs.old, freqs.new);
1892
1893 cpufreq_freq_transition_begin(policy, &freqs);
1894 }
1895
1896 retval = cpufreq_driver->target_index(policy, index);
1897 if (retval)
1898 pr_err("%s: Failed to change cpu frequency: %d\n", __func__,
1899 retval);
1900
1901 if (notify) {
1902 cpufreq_freq_transition_end(policy, &freqs, retval);
1903
1904 /*
1905 * Failed after setting to intermediate freq? Driver should have
1906 * reverted back to initial frequency and so should we. Check
1907 * here for intermediate_freq instead of get_intermediate, in
1908 * case we haven't switched to intermediate freq at all.
1909 */
1910 if (unlikely(retval && intermediate_freq)) {
1911 freqs.old = intermediate_freq;
1912 freqs.new = policy->restore_freq;
1913 cpufreq_freq_transition_begin(policy, &freqs);
1914 cpufreq_freq_transition_end(policy, &freqs, 0);
1915 }
1916 }
1917
1918 return retval;
1919 }
19 static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
20 unsigned int event)
21 {
22 switch (event) {
23 case CPUFREQ_GOV_START:
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->min, event);
27 __cpufreq_driver_target(policy, policy->min,
28 CPUFREQ_RELATION_L);
29 break;
30 default:
31 break;
32 }
33 return 0;
34 }
performance 正好相反
19 static int cpufreq_governor_performance(struct cpufreq_policy *policy,
20 unsigned int event)
21 {
22 switch (event) {
23 case CPUFREQ_GOV_START:
24 case CPUFREQ_GOV_LIMITS:
25 pr_debug("setting to %u kHz because of event %u\n",
26 policy->max, event);
27 __cpufreq_driver_target(policy, policy->max,
28 CPUFREQ_RELATION_H);
29 break;
30 default:
31 break;
32 }
33 return 0;
34 }
也是直接调用__cpufreq_driver_target 以最大频率运行.
我们看看__cpufreq_driver_target的实现。
可见cpufreq driver设定freq有两种方式
第一种:
如果driver实现了target,则直接调用target设定hw寄存器的频率.
1953 if (cpufreq_driver->target)
1954 return cpufreq_driver->target(policy, target_freq, relation);
第二种是:必须实现cpufreq_driver->target_index方法.
先得到freq 表
1959 freq_table = cpufreq_frequency_get_table(policy->cpu);
调用cpufreq_frequency_table_target 根据relation是CPUFREQ_RELATION_H 或者 CPUFREQ_RELATION_L的得到最大或最小频率.
1965 retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
1966 relation, &index);
调用__target_index 设定频率.
1921 int __cpufreq_driver_target(struct cpufreq_policy *policy,
1922 unsigned int target_freq,
1923 unsigned int relation)
1924 {
1925 unsigned int old_target_freq = target_freq;
1926 struct cpufreq_frequency_table *freq_table;
1927 int index, retval;
1928
1929 if (cpufreq_disabled())
1930 return -ENODEV;
1931
1932 /* Make sure that target_freq is within supported range */
1933 if (target_freq > policy->max)
1934 target_freq = policy->max;
1935 if (target_freq < policy->min)
1936 target_freq = policy->min;
1937
1938 pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
1939 policy->cpu, target_freq, relation, old_target_freq);
1940
1941 /*
1942 * This might look like a redundant call as we are checking it again
1943 * after finding index. But it is left intentionally for cases where
1944 * exactly same freq is called again and so we can save on few function
1945 * calls.
1946 */
1947 if (target_freq == policy->cur)
1948 return 0;
1949
1950 /* Save last value to restore later on errors */
1951 policy->restore_freq = policy->cur;
1952
1953 if (cpufreq_driver->target)
1954 return cpufreq_driver->target(policy, target_freq, relation);
1955
1956 if (!cpufreq_driver->target_index)
1957 return -EINVAL;
1958
1959 freq_table = cpufreq_frequency_get_table(policy->cpu);
1960 if (unlikely(!freq_table)) {
1961 pr_err("%s: Unable to find freq_table\n", __func__);
1962 return -EINVAL;
1963 }
1964
1965 retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
1966 relation, &index);
1967 if (unlikely(retval)) {
1968 pr_err("%s: Unable to find matching freq\n", __func__);
1969 return retval;
1970 }
1971
1972 if (freq_table[index].frequency == policy->cur)
1973 return 0;
1974
1975 return __target_index(policy, freq_table, index);
1976 }
1977 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
__target_index 会根据cpufreq_driver->flags 来判断是修改freq是同步还是异步操作,如果是异步就直接调用
cpufreq_driver->target_index 设定频率,如果是同步就要调用cpufreq_freq_transition_begin和cpufreq_freq_transition_end 做一些包含.
1867 static int __target_index(struct cpufreq_policy *policy,
1868 struct cpufreq_frequency_table *freq_table, int index)
1869 {
1870 struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0};
1871 unsigned int intermediate_freq = 0;
1872 int retval = -EINVAL;
1873 bool notify;
1874
1875 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
1876 if (notify) {
1877 /* Handle switching to intermediate frequency */
1878 if (cpufreq_driver->get_intermediate) {
1879 retval = __target_intermediate(policy, &freqs, index);
1880 if (retval)
1881 return retval;
1882
1883 intermediate_freq = freqs.new;
1884 /* Set old freq to intermediate */
1885 if (intermediate_freq)
1886 freqs.old = freqs.new;
1887 }
1888
1889 freqs.new = freq_table[index].frequency;
1890 pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
1891 __func__, policy->cpu, freqs.old, freqs.new);
1892
1893 cpufreq_freq_transition_begin(policy, &freqs);
1894 }
1895
1896 retval = cpufreq_driver->target_index(policy, index);
1897 if (retval)
1898 pr_err("%s: Failed to change cpu frequency: %d\n", __func__,
1899 retval);
1900
1901 if (notify) {
1902 cpufreq_freq_transition_end(policy, &freqs, retval);
1903
1904 /*
1905 * Failed after setting to intermediate freq? Driver should have
1906 * reverted back to initial frequency and so should we. Check
1907 * here for intermediate_freq instead of get_intermediate, in
1908 * case we haven't switched to intermediate freq at all.
1909 */
1910 if (unlikely(retval && intermediate_freq)) {
1911 freqs.old = intermediate_freq;
1912 freqs.new = policy->restore_freq;
1913 cpufreq_freq_transition_begin(policy, &freqs);
1914 cpufreq_freq_transition_end(policy, &freqs, 0);
1915 }
1916 }
1917
1918 return retval;
1919 }