cpu_freq之切换governor.
2016-08-15 15:09
323 查看
系统中提供五个governor(conservative ondemand userspace powersave performance )策略来选择,但是具体是在哪里选择的呢?
不管从哪里选择都是要调用cpufreq_set_policy来设定governor
static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy)
下来看看具体都是谁调用cpufreq_set_policy
1):可以在user space设定min_freq和max_freq时候来改变governor
635 #define store_one(file_name, object) \
636 static ssize_t store_##file_name \
637 (struct cpufreq_policy *policy, const char *buf, size_t count) \
648 temp = new_policy.object; \
649 ret = cpufreq_set_policy(policy, &new_policy); \
650 if (!ret) \
651 policy->user_policy.object = temp; \
652 \
653 return ret ? ret : count; \
654 }
655
656 store_one(scaling_min_freq, min);
657 store_one(scaling_max_freq, max);
2):user space 直接通过文件系统的scaling_governor 来设定governor.
689 static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
690 const char *buf, size_t count)
691 {
706 ret = cpufreq_set_policy(policy, &new_policy);
707 return ret ? ret : count;
708 }
3):调用cpufreq_register_driver的时候会调用cpufreq_init_policy 来设定一个默认的governor.
993 static int cpufreq_init_policy(struct cpufreq_policy *policy)
994 {
1021 /* set default policy */
1022 return cpufreq_set_policy(policy, &new_policy);
1023 }
4):可以调用kernel space直接调用cpufreq_update_policy 来更新governor.
2243 int cpufreq_update_policy(unsigned int cpu)
2244 {
2274
2275 ret = cpufreq_set_policy(policy, &new_policy);
2276
2277 unlock:
2278 up_write(&policy->rwsem);
2279
2280 cpufreq_cpu_put(policy);
2281 return ret;
2282 }
可见都是主动调用cpufreq_set_policy来设置governor,kernel 不会自动切换governor。
下来我们看看cpufreq_set_policy是如何切换cpufreq_set_policy的。
2164行调用cpufreq_driver->verify验证cpu speed是否在合理范围内.
2169行发送通知链告诉其他相关模块现在要开始调整cpufreq了.
2176行再次调用cpufreq_driver->verify验证cpu speed是否在合理范围内
2181行发送CPUFREQ_NOTIFY通知链
2190行如果driver的setplicy不为NULL 则调用cpufreq_driver->setpolicy
2196行如果新旧governor是一样的,则调用cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)。后面在分析CPUFREQ_GOV_LIMITS是啥意思.
2204行保存旧的governor.
2206行如果旧的governor不为null,则停止然后退出旧的governor.
2213行调用cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT),然后开始cpufreq_start_governor(policy) 这个governor。
如果成功的话,就在2218行退出了
从2225行到2233行,如果新的governor 切换失败,就从来开始旧的governor.
2145 static int cpufreq_set_policy(struct cpufreq_policy *policy,
2146 struct cpufreq_policy *new_policy)
2147 {
2148 struct cpufreq_governor *old_gov;
2149 int ret;
2150
2151 pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
2152 new_policy->cpu, new_policy->min, new_policy->max);
2153
2154 memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
2155
2156 /*
2157 * This check works well when we store new min/max freq attributes,
2158 * because new_policy is a copy of policy with one field updated.
2159 */
2160 if (new_policy->min > new_policy->max)
2161 return -EINVAL;
2162
2163 /* verify the cpu speed can be set within this limit */
2164 ret = cpufreq_driver->verify(new_policy);
2165 if (ret)
2166 return ret;
2167
2168 /* adjust if necessary - all reasons */
2169 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
2170 CPUFREQ_ADJUST, new_policy);
2171
2172 /*
2173 * verify the cpu speed can be set within this limit, which might be
2174 * different to the first one
2175 */
2176 ret = cpufreq_driver->verify(new_policy);
2177 if (ret)
2178 return ret;
2179
2180 /* notification of the new policy */
2181 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
2182 CPUFREQ_NOTIFY, new_policy);
2183
2184 policy->min = new_policy->min;
2185 policy->max = new_policy->max;
2186
2187 pr_debug("new min and max freqs are %u - %u kHz\n",
2188 policy->min, policy->max);
2189
2190 if (cpufreq_driver->setpolicy) {
2191 policy->policy = new_policy->policy;
2192 pr_debug("setting range\n");
2193 return cpufreq_driver->setpolicy(new_policy);
2194 }
2195
2196 if (new_policy->governor == policy->governor) {
2197 pr_debug("cpufreq: governor limits update\n");
2198 return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
2199 }
2200
2201 pr_debug("governor switch\n");
2202
2203 /* save old, working values */
2204 old_gov = policy->governor;
2205 /* end old governor */
2206 if (old_gov) {
2207 cpufreq_stop_governor(policy);
2208 cpufreq_exit_governor(policy);
2209 }
2210
2211 /* start new governor */
2212 policy->governor = new_policy->governor;
2213 ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
2214 if (!ret) {
2215 ret = cpufreq_start_governor(policy);
2216 if (!ret) {
2217 pr_debug("cpufreq: governor change\n");
2218 return 0;
2219 }
2220 cpufreq_exit_governor(policy);
2221 }
2222
2223 /* new governor failed, so re-start old one */
2224 pr_debug("starting governor %s failed\n", policy->governor->name);
2225 if (old_gov) {
2226 policy->governor = old_gov;
2227 if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
2228 policy->governor = NULL;
2229 else
2230 cpufreq_start_governor(policy);
2231 }
2232
2233 return ret;
2234 }
下来我们看看cpufreq_governor 这个函数具体做了啥事.
2005行如果系统已经开始suspend,则退出.
2011行如果新的pplicy->governor 为NULL,则退出.
2014~2026是判断hw的transition latency是否太长,一般走不到。
2034行调用具体governor来切换governor.
2036~2043处理CPUFREQ_GOV_POLICY_INIT和CPUFREQ_GOV_POLICY_EXIT。模块技术的加和减,奇怪的是没有处理CPUFREQ_GOV_LIMITS,所以这个event 肯定是具体的governor来处理的.
2000 static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
2001 {
2002 int ret;
2003
2004 /* Don't start any governor operations if we are entering suspend */
2005 if (cpufreq_suspended)
2006 return 0;
2007 /*
2008 * Governor might not be initiated here if ACPI _PPC changed
2009 * notification happened, so check it.
2010 */
2011 if (!policy->governor)
2012 return -EINVAL;
2013
2014 if (policy->governor->max_transition_latency &&
2015 policy->cpuinfo.transition_latency >
2016 policy->governor->max_transition_latency) {
2017 struct cpufreq_governor *gov = cpufreq_fallback_governor();
2018
2019 if (gov) {
2020 pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
2021 policy->governor->name, gov->name);
2022 policy->governor = gov;
2023 } else {
2024 return -EINVAL;
2025 }
2026 }
2027
2028 if (event == CPUFREQ_GOV_POLICY_INIT)
2029 if (!try_module_get(policy->governor->owner))
2030 return -EINVAL;
2031
2032 pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
2033
2034 ret = policy->governor->governor(policy, event);
2035
2036 if (event == CPUFREQ_GOV_POLICY_INIT) {
2037 if (ret)
2038 module_put(policy->governor->owner);
2039 else
2040 policy->governor->initialized++;
2041 } else if (event == CPUFREQ_GOV_POLICY_EXIT) {
2042 policy->governor->initialized--;
2043 module_put(policy->governor->owner);
2044 }
2045
2046 return ret;
2047 }
再来看看cpufreq_start_governor。cpufreq_start_governor主要是开始一个新的policy.
2049 static int cpufreq_start_governor(struct cpufreq_policy *policy)
2050 {
2051 int ret;
2052
2053 if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
2054 cpufreq_update_current_freq(policy);
2055
2056 ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
2057 return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
2058 }
2054行调用cpufreq_update_current_freq来更新freq。1562行先调用get函数得到freq,这也是为什么cpufreq_start_governor中判断get函数不能为空的原因.
1555 static unsigned int cpufreq_update_current_freq(struct cpufreq_policy *policy)
1556 {
1557 unsigned int new_freq;
1558
1559 if (cpufreq_suspended)
1560 return 0;
1561
1562 new_freq = cpufreq_driver->get(policy->cpu);
1563 if (!new_freq)
1564 return 0;
1565
1566 if (!policy->cur) {
1567 pr_debug("cpufreq: Driver did not initialize current freq\n");
1568 policy->cur = new_freq;
1569 } else if (policy->cur != new_freq && has_target()) {
1570 cpufreq_out_of_sync(policy, new_freq);
1571 }
1572
1573 return new_freq;
1574 }
2056行又调用cpufreq_governor函数,不过传递的event是CPUFREQ_GOV_START,让具体的governor来处理.
不管从哪里选择都是要调用cpufreq_set_policy来设定governor
static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy)
下来看看具体都是谁调用cpufreq_set_policy
1):可以在user space设定min_freq和max_freq时候来改变governor
635 #define store_one(file_name, object) \
636 static ssize_t store_##file_name \
637 (struct cpufreq_policy *policy, const char *buf, size_t count) \
648 temp = new_policy.object; \
649 ret = cpufreq_set_policy(policy, &new_policy); \
650 if (!ret) \
651 policy->user_policy.object = temp; \
652 \
653 return ret ? ret : count; \
654 }
655
656 store_one(scaling_min_freq, min);
657 store_one(scaling_max_freq, max);
2):user space 直接通过文件系统的scaling_governor 来设定governor.
689 static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
690 const char *buf, size_t count)
691 {
706 ret = cpufreq_set_policy(policy, &new_policy);
707 return ret ? ret : count;
708 }
3):调用cpufreq_register_driver的时候会调用cpufreq_init_policy 来设定一个默认的governor.
993 static int cpufreq_init_policy(struct cpufreq_policy *policy)
994 {
1021 /* set default policy */
1022 return cpufreq_set_policy(policy, &new_policy);
1023 }
4):可以调用kernel space直接调用cpufreq_update_policy 来更新governor.
2243 int cpufreq_update_policy(unsigned int cpu)
2244 {
2274
2275 ret = cpufreq_set_policy(policy, &new_policy);
2276
2277 unlock:
2278 up_write(&policy->rwsem);
2279
2280 cpufreq_cpu_put(policy);
2281 return ret;
2282 }
可见都是主动调用cpufreq_set_policy来设置governor,kernel 不会自动切换governor。
下来我们看看cpufreq_set_policy是如何切换cpufreq_set_policy的。
2164行调用cpufreq_driver->verify验证cpu speed是否在合理范围内.
2169行发送通知链告诉其他相关模块现在要开始调整cpufreq了.
2176行再次调用cpufreq_driver->verify验证cpu speed是否在合理范围内
2181行发送CPUFREQ_NOTIFY通知链
2190行如果driver的setplicy不为NULL 则调用cpufreq_driver->setpolicy
2196行如果新旧governor是一样的,则调用cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)。后面在分析CPUFREQ_GOV_LIMITS是啥意思.
2204行保存旧的governor.
2206行如果旧的governor不为null,则停止然后退出旧的governor.
2213行调用cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT),然后开始cpufreq_start_governor(policy) 这个governor。
如果成功的话,就在2218行退出了
从2225行到2233行,如果新的governor 切换失败,就从来开始旧的governor.
2145 static int cpufreq_set_policy(struct cpufreq_policy *policy,
2146 struct cpufreq_policy *new_policy)
2147 {
2148 struct cpufreq_governor *old_gov;
2149 int ret;
2150
2151 pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
2152 new_policy->cpu, new_policy->min, new_policy->max);
2153
2154 memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
2155
2156 /*
2157 * This check works well when we store new min/max freq attributes,
2158 * because new_policy is a copy of policy with one field updated.
2159 */
2160 if (new_policy->min > new_policy->max)
2161 return -EINVAL;
2162
2163 /* verify the cpu speed can be set within this limit */
2164 ret = cpufreq_driver->verify(new_policy);
2165 if (ret)
2166 return ret;
2167
2168 /* adjust if necessary - all reasons */
2169 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
2170 CPUFREQ_ADJUST, new_policy);
2171
2172 /*
2173 * verify the cpu speed can be set within this limit, which might be
2174 * different to the first one
2175 */
2176 ret = cpufreq_driver->verify(new_policy);
2177 if (ret)
2178 return ret;
2179
2180 /* notification of the new policy */
2181 blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
2182 CPUFREQ_NOTIFY, new_policy);
2183
2184 policy->min = new_policy->min;
2185 policy->max = new_policy->max;
2186
2187 pr_debug("new min and max freqs are %u - %u kHz\n",
2188 policy->min, policy->max);
2189
2190 if (cpufreq_driver->setpolicy) {
2191 policy->policy = new_policy->policy;
2192 pr_debug("setting range\n");
2193 return cpufreq_driver->setpolicy(new_policy);
2194 }
2195
2196 if (new_policy->governor == policy->governor) {
2197 pr_debug("cpufreq: governor limits update\n");
2198 return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
2199 }
2200
2201 pr_debug("governor switch\n");
2202
2203 /* save old, working values */
2204 old_gov = policy->governor;
2205 /* end old governor */
2206 if (old_gov) {
2207 cpufreq_stop_governor(policy);
2208 cpufreq_exit_governor(policy);
2209 }
2210
2211 /* start new governor */
2212 policy->governor = new_policy->governor;
2213 ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
2214 if (!ret) {
2215 ret = cpufreq_start_governor(policy);
2216 if (!ret) {
2217 pr_debug("cpufreq: governor change\n");
2218 return 0;
2219 }
2220 cpufreq_exit_governor(policy);
2221 }
2222
2223 /* new governor failed, so re-start old one */
2224 pr_debug("starting governor %s failed\n", policy->governor->name);
2225 if (old_gov) {
2226 policy->governor = old_gov;
2227 if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
2228 policy->governor = NULL;
2229 else
2230 cpufreq_start_governor(policy);
2231 }
2232
2233 return ret;
2234 }
下来我们看看cpufreq_governor 这个函数具体做了啥事.
2005行如果系统已经开始suspend,则退出.
2011行如果新的pplicy->governor 为NULL,则退出.
2014~2026是判断hw的transition latency是否太长,一般走不到。
2034行调用具体governor来切换governor.
2036~2043处理CPUFREQ_GOV_POLICY_INIT和CPUFREQ_GOV_POLICY_EXIT。模块技术的加和减,奇怪的是没有处理CPUFREQ_GOV_LIMITS,所以这个event 肯定是具体的governor来处理的.
2000 static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
2001 {
2002 int ret;
2003
2004 /* Don't start any governor operations if we are entering suspend */
2005 if (cpufreq_suspended)
2006 return 0;
2007 /*
2008 * Governor might not be initiated here if ACPI _PPC changed
2009 * notification happened, so check it.
2010 */
2011 if (!policy->governor)
2012 return -EINVAL;
2013
2014 if (policy->governor->max_transition_latency &&
2015 policy->cpuinfo.transition_latency >
2016 policy->governor->max_transition_latency) {
2017 struct cpufreq_governor *gov = cpufreq_fallback_governor();
2018
2019 if (gov) {
2020 pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
2021 policy->governor->name, gov->name);
2022 policy->governor = gov;
2023 } else {
2024 return -EINVAL;
2025 }
2026 }
2027
2028 if (event == CPUFREQ_GOV_POLICY_INIT)
2029 if (!try_module_get(policy->governor->owner))
2030 return -EINVAL;
2031
2032 pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
2033
2034 ret = policy->governor->governor(policy, event);
2035
2036 if (event == CPUFREQ_GOV_POLICY_INIT) {
2037 if (ret)
2038 module_put(policy->governor->owner);
2039 else
2040 policy->governor->initialized++;
2041 } else if (event == CPUFREQ_GOV_POLICY_EXIT) {
2042 policy->governor->initialized--;
2043 module_put(policy->governor->owner);
2044 }
2045
2046 return ret;
2047 }
再来看看cpufreq_start_governor。cpufreq_start_governor主要是开始一个新的policy.
2049 static int cpufreq_start_governor(struct cpufreq_policy *policy)
2050 {
2051 int ret;
2052
2053 if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
2054 cpufreq_update_current_freq(policy);
2055
2056 ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
2057 return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
2058 }
2054行调用cpufreq_update_current_freq来更新freq。1562行先调用get函数得到freq,这也是为什么cpufreq_start_governor中判断get函数不能为空的原因.
1555 static unsigned int cpufreq_update_current_freq(struct cpufreq_policy *policy)
1556 {
1557 unsigned int new_freq;
1558
1559 if (cpufreq_suspended)
1560 return 0;
1561
1562 new_freq = cpufreq_driver->get(policy->cpu);
1563 if (!new_freq)
1564 return 0;
1565
1566 if (!policy->cur) {
1567 pr_debug("cpufreq: Driver did not initialize current freq\n");
1568 policy->cur = new_freq;
1569 } else if (policy->cur != new_freq && has_target()) {
1570 cpufreq_out_of_sync(policy, new_freq);
1571 }
1572
1573 return new_freq;
1574 }
2056行又调用cpufreq_governor函数,不过传递的event是CPUFREQ_GOV_START,让具体的governor来处理.
相关文章推荐
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态调频系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- linux cpufreq framework(4)_cpufreq governor
- linux cpufreq framework(4)_cpufreq governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- Linux动态频率调节系统CPUFreq之三:governor
- cpu_freq之注册governor.
- About cpu freq governor fixing for periodic
- Linux动态频率调节系统CPUFreq之一:概述
- Linux动态频率调节系统CPUFreq之一:概述
- linux cpufreq framework(1)_概述
- win7-tensorflow查看当前运算器件及无法正常切换CPU/GPU运算器件问题解决方案
- Linux动态频率调节系统CPUFreq之二:核心(core)架构与API
- 1.Linux中超频及cpufreq相关汇总