cpufreq 之powersave和performance governer的实现

我们再来看看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 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值