系统中提供五个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来处理.

cpu_freq之切换governor.相关推荐

  1. linux cpufreq framework(3)_cpufreq core

    1. 前言 前文(Linux cpufreq framework(2)_cpufreq driver)从平台驱动工程师的角度,简单的介绍了编写一个cpufreq driver的大概步骤.但要更深入理解 ...

  2. 瑞芯微rv1126超频笔记

    Print Encode Frame Rate enable print fps log echo 0x100 > /sys/module/rk_vcodec/parameters/mpp_de ...

  3. ACPI相关(11)- PCC实例

    二.PCC实例应用 2.1 概述 平台通信通道(PCC)是用于PC和服务器平台的ACPI规范定义的机制,作为平台固件(如系统固件或管理控制器)和操作系统(OSPM)之间双向通信的标准机制. PCC是一 ...

  4. Tegra3 vSMP架构Android运行时CPU热插拔及高低功耗CPU切换

    Tegra3采用vSMP(VariableSymmetric Multiprocessing)架构,共5个cortex-a9处理器,其中4个为高性能设计,1个为低功耗设计: 在系统运行过程中,会根据C ...

  5. Linux cpuidle framework(4)_menu governor

    Linux cpuidle framework(4)_menu governor menu governor的主要任务就转化为两个:1. 根据系统的运行情况,预测CPU将在C state中停留的时间( ...

  6. CPU动态调频二:interactive governor

    Linux提供了多种governor供用户选择,这里以interactive为例,毕竟现在的android手机中都是采用该governor. 基于linux 3.14 以下代码若未指明位置则默认在dr ...

  7. Schedutil governor情景分析

    前言 内核工匠在之前的几篇文章中已经详细介绍了CPU的调频子系统的软件框架,本文把重点放在了schedutil governor(后文称之sugov)的代码逻辑.通过详细的代码级别的分析,希望能够帮助 ...

  8. [cpufreq governor] schedutil governor解析

    1.schedutil governor相关的结构体说明 struct sugov_policy { struct cpufreq_policy *policy; /*cpu freq的policy* ...

  9. MTK schedplus CPU Governor

    一,代码分析 定义 CONFIG_CPU_FREQ_GOV_SCHEDPLUS=y 1. @LINUX/android/kernel-4.9/drivers/misc/mediatek/sched/K ...

最新文章

  1. 机器不学习:浅显易懂!「高中数学」读懂梯度下降的数学原理
  2. (转)Ubuntu12.04上NFS Server安装使用过程
  3. Oracle表里的照片怎么导出来,如何导出oracle数据库中某张表到excel_oracle数据库表格导出到excel...
  4. 数据结构 二叉树的遍历
  5. 三、Netty的粘包半包问题解决
  6. ABP从入门到精通(5):.扩展国际化语言资源
  7. Silverlight 5 Beta新特性[3]多窗口支持
  8. creo图纸管理系统 creo企业图纸管理方案
  9. 计算机桌面的任务栏,计算机桌面出现两个任务栏怎么办?
  10. 锐捷校园网:小米mini路由刷Padavan固件实现wifi上网
  11. AlphaGo人肉臂黄士杰:我的使命完成 阿尔法狗项目结束 | 重磅
  12. 【转】TinyXML2 入门教程
  13. TGRS2022/遥感:An Empirical Study of Remote Sensing Pretraining遥感预训练的实证研究
  14. Ubuntu16.04+智能车+YOLO
  15. preg_replace() 正则替换所有符合条件的字符串
  16. android 壁纸软件 宝宝,宝宝巴士桌面软件下载
  17. 传感器和变送器的区别
  18. php7.4安装配置,CentOS环境下安装配置PHP 7.4的方法
  19. iphone中获取屏幕分辨率的方法
  20. itchat分析微信好友的个性签名

热门文章

  1. 软件需求分析-需求开发-需求定义与需求捕获
  2. 【Docker】之容器文件的上传和下载
  3. JAVA毕业设计高校勤工助学管理系统计算机源码+lw文档+系统+调试部署+数据库
  4. 与豆瓣网杨勃聊天(续)
  5. 小米3 android,小米手機
  6. OA系统排名?OA办公系统怎么选?
  7. 新基建 数据中心样板案例丨中国联通贵安云数据中心微模块机房运营
  8. USB VCP虚拟串口通讯详细配置步骤(STM32H732)
  9. hdu 2546 饭卡(P01-背包)
  10. metatrader4下载