今天学习了cpu_cooling.c源文件,路径在drivers/thermal/cpu_cooling.c。源代码地址:https://elixir.bootlin.com/linux/v5.4/source/drivers/thermal/cpu_cooling.c
1 文件内容整体描述
cpu_cooling.c主要提供了thermal管理中注册cpufreq cooling device的接口函数,还包含注册时需要调用的函数。这些函数都是kernel的原生框架内容,不同的厂商平台可以依据此框架注册适合于自己平台的cpufreq cooling device。
2 主要数据结构
struct cpufreq_cooling_device {
int id; //设备ID
u32 last_load; //最近一次的负载
unsigned int cpufreq_state;
unsigned int max_level; //最大冷却等级
struct freq_table *freq_table; //频率和功率对应表,频率按降序排列,freq_table数据结构如下所示
struct cpufreq_policy *policy; //cpu对应的policy
struct list_head node;
struct time_in_idle *idle_time;
struct freq_qos_request qos_req;
};
struct freq_table {
u32 frequency;
u32 power;
};
/* Bind cpufreq callbacks to thermal cooling device ops */
//cpufreq cooling device的操作函数,注意下面这两个数据结构的区别
static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
.get_max_state = cpufreq_get_max_state,
.get_cur_state = cpufreq_get_cur_state,
.set_cur_state = cpufreq_set_cur_state,
};
static struct thermal_cooling_device_ops cpufreq_power_cooling_ops = {
.get_max_state = cpufreq_get_max_state,
.get_cur_state = cpufreq_get_cur_state,
.set_cur_state = cpufreq_set_cur_state,
.get_requested_power = cpufreq_get_requested_power,
.state2power = cpufreq_state2power,
.power2state = cpufreq_power2state,
};
3 主要接口函数
1 . cpufreq_cooling_register
函数功能:注册cpufreq cooling device,可支持多个cpufreq cooling device注册,其名称为"thermal-cpufreq-%x"
参数:cpufreq policy
返回:注册成功,返回thermal_cooling_device数据结构。
可以看到注册的cpufreq_cooling_device本质上是thermal_cooling_device。
struct thermal_cooling_device *
cpufreq_cooling_register(struct cpufreq_policy *policy)
{
return __cpufreq_cooling_register(NULL, policy, 0);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
2 . of_cpufreq_cooling_register
函数功能:注意和cpufreq_cooling_register进行区分,其和cpufreq_cooling_register函数功能相同,都是注册thermal-cpufreq-%x的cpufreq cooling device,不同的是这个函数中的cpufreq cooling device是与设备树提供的节点相关联的。在这个接口中,所注册的cooling device引入了cpu功耗模型的应用,前提是cpus都注册了它们相对应的OPP(这一部分的注册在OPP模块中,本文不作详述)。它还可以根据设备树提供的能效模型数据来计算cpu的静态功耗。如果芯片具备能效模型(一般由ASIC提供),那么最好用这个接口。
参数:cpufreq policy
返回:注册成功,返回thermal_cooling_device数据结构。
struct thermal_cooling_device *
of_cpufreq_cooling_register(struct cpufreq_policy *policy)
{
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
struct thermal_cooling_device *cdev = NULL;
u32 capacitance = 0;
if (!np) {
pr_err("cpu_cooling: OF node not available for cpu%d\n",
policy->cpu);
return NULL;
}
if (of_find_property(np, "#cooling-cells", NULL)) {
of_property_read_u32(np, "dynamic-power-coefficient",
&capacitance);
cdev = __cpufreq_cooling_register(np, policy, capacitance);
if (IS_ERR(cdev)) {
pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n",
policy->cpu, PTR_ERR(cdev));
cdev = NULL;
}
}
of_node_put(np);
return cdev;
}
3 . __cpufreq_cooling_register
1和2两个函数最核心的调用是调用函数__cpufreq_cooling_register,其参数不同,决定了其功能上的不同,这个函数很重要。
函数功能:注册cpufreq cooling device。
参数:
np 对应cooling device的设备树节点,是一个指针,指向device_node类型的数据结构;
policy cpufreq policy;
capacitance 对应cpu的动态功耗系数(在of_cpufreq_cooling_register函数中可以看到这个值是从设备树中policy->cpu的节点属性拿到的)。
返回:thermal_cooling_device数据结构。
下面我们来看下这个函数的流程,注意结合上面说到的关键数据结构。
在流程中update_freq_table也是比较重要的一个函数,该函数定义同样是在cpu_cooling.c文件中。
4 . update_freq_table
函数功能:更新freq_table,为freq_table添加相应的功率值。这个table将在cpu_power_to_freq()和cpu_freq_to_power()中被用来进行频率和功率的转换。power单位mW,频率单位KHz。最终获得的table仍以频率降序排列。特别需要注意,power为动态功耗。
参数:
cpufreq_cdev 被更新的freq_table所属的cpufreq cooling device
capacitance cpus的动态功耗系数
返回:成功返回0,如果OPP还没注册好或者内存溢出返回-EINVAL。
函数流程图如下:
以上流程中对电压、频率、功率做了一些数量级的处理,这里只是简单描述计算过程,数量级处理请详细参见源码。
另外,注意到这里power的计算公式为:
power = capacitance × freq × voltage × voltage
这是cpu的动态功耗计算公式。(其实从capacitance就可以看出是动态功耗,因为在注释中明确指出capacitance指的是动态功耗系数)
也就是说freq_table中的freq对应的power是cpu的动态功耗哦!!
有关静态功耗和动态功耗请参见文末附加内容。
附:芯片的功耗组成知识点
芯片的功耗取决于其中的CMOS电路的功耗,这些功耗主要由动态功耗(dynamic_power)和静态功耗(static_power)两部分组成。
(1)动态功耗 = 开关功耗 + 短路功耗,开关功耗就是在mos电路发生电平反转时的功耗(常见CLK),而在电平翻转的瞬间,mos电路中的nmos和pmos有那么一刻pmos和nmos同时导通,此时电源和地之间短路,形成短路电流,造成短路功耗。
(2)静态功耗
CMOS电路中场效应管(FET,Field Effect Transistor)的泄漏电流引起的功耗,也叫做leakage power。
功耗计算公式如下:
其中:
C 负载电容的容值;V 工作电压;A 当前频率下电路的平均翻转率;f 工作频率
以上。
【声明】本博文为个人学习笔记,仅供参考。转发请注明出处。如发现有误,还请不吝赐教,多谢!