cpufreq 之powersave和performance governer的实现

    xiaoxiao2025-12-30  10

    我们再来看看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 }
    转载请注明原文地址: https://ju.6miu.com/read-1305483.html
    最新回复(0)