1. thermal简介
thermal子系统主要用来监测和调节CPU、GPU等芯片或设备的温度。三个主要结构体的关系:从thermal_zone_device获取温度后,根据governor指定的策略,来控制thermal_cooling_device进行温度调节。
结构体 | 描述 | 举例 |
---|---|---|
struct thermal_zone_device | 对温度调节域的抽象,包含配置信息和传感器信息 | NTC、Temperature Sensor ADC(TSADC) |
struct thermal_cooling_device | 用于冷却的设备 | CPU、GPU、风扇 |
struct thermal_governor | 温度调节策略 | power_allocator、user_space、step_wise、bang_bang、fair_share |
CPU和GPU可以通过调压调频来调节功耗,也可以作为cooling device。
2. thermal子系统初始化
thermal_init实现的工作比较简单
- 如果使能了CONFIG_THERMAL_NETLINK,就注册thermal_gnl_family。
- 注册governor,并设置def_governor。
- 注册thermal_class。
- 注册thermal_pm_nb通知链。
2.1. thermal_governor注册
governor由THERMAL_GOVERNOR_DECLARE静态声明。 在thermal_init中,thermal_register_governors会注册thermal_governor,将governor添加到thermal_governor_list链表,并根据DEFAULT_THERMAL_GOVERNOR,设定def_governor。
1drivers/thermal/gov_bang_bang.c
2113:THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);
3drivers/thermal/gov_fair_share.c
4122:THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);
5drivers/thermal/gov_power_allocator.c
6744:THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);
7drivers/thermal/gov_step_wise.c
8177:THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);
9drivers/thermal/gov_user_space.c
1056:THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);
thermal_register_governor在注册一个新的governor时,还会遍历thermal_tz_list链表,尝试绑定thermal zone。但是thermal_init的调用时机比较早,通常来说thermal_tz_list链表是空的。
3. thermal_zone_device
thermal_zone_device是对温度调节区域的一个抽象,这个区域可以是CPU,也可以是GPU或其他设备。thermal_zone_device会对应一个物理传感器或多个物理传感器,也可以对应传感器的一个通道或多个通道。
thermal_zone_device包含一些配置信息,以及温度读取和调节的操作函数。thermal_zone_device配置信息记录在dtb中的thermal-zones
节点。
3.1. 主要的dts属性
主要的属性描述参考Documentation/devicetree/bindings/thermal/
下的几个文件。
1thermal-cooling-devices.yaml
2thermal-idle.yaml
3thermal-sensor.yaml
4thermal-zones.yaml
在probe温度传感器时,如"rockchip,rk3399-tsadc",调用devm_thermal_of_zone_register或thermal_of_zone_register查找包含此温度传感器的thermal-zones
节点。比如:
1 tsadc: tsadc@ff260000 {
2 compatible = "rockchip,rk3399-tsadc";
3 ...
4 };
5 ...
6 thermal_zones: thermal-zones {
7 cpu_thermal: cpu-thermal {
8 polling-delay-passive = <100>;
9 polling-delay = <1000>;
10
11 thermal-sensors = <&tsadc 0>;
12 ...
thermal-zones
下的每个子节点对应一个thermal_zone_device设备
node | func |
---|---|
thermal-zones | of_thermal_zone_find |
thermal-sensors | of_thermal_zone_find |
trips | thermal_of_trips_init |
polling-delay | thermal_of_monitor_init |
polling-delay-passive | thermal_of_monitor_init |
coefficients | thermal_of_parameters_init |
sustainable-power | thermal_of_parameters_init |
cooling-maps | thermal_of_for_each_cooling_maps |
thermal_of_for_each_cooling_maps bind时会用。
- polling-delay:温度未超过阈值时的轮询时间,单位ms,为0表示不做轮询
- polling-delay-passive:温度超过阈值时的轮询时间,单位ms,为0表示不做轮询
- coefficients:线性方程系数的数组,该线性方程将该thermal-zone中列出的所有传感器绑定在一起
- sustainable-power:该thermal-zone在所需控制温度下可耗散的可持续功率(热量)的估计值,单位mW
3.1.1. thermal_of_populate_trip
- temperature:阈值温度,单位千分之一摄氏度
- hysteresis:滞后温度,表示当下降到temperature – hysteresis度时解除温度调节,防止解除温度调节后温度回升导致频繁启动温度调节
- type:阈值类型:active/passive/hot/critical,与enum thermal_trip_type对应
3.2. thermal-sensor注册
thermal_zone_device.devdata
记录了sensor相关的信息。通过各个设备的驱动中调用thermal_zone_of_sensor_register及其相关函数进行注册。
4. cooling device register
4.1. thermal_cooling_device注册
thermal_cooling_device由其对应设备在probe时注册,如cpufreq_cooling_register。注册的设备最终会添加到thermal_cdev_list链表。
5. bind thermal and cooling device
- contribution:cooling_device在thermal-zone的权重
- trip:指向触发温度调节对应的温度阈值trip节点
- cooling-device:包含cooling_device、最小和最大冷却状态的列表
6. 温度调节
6.1. 温度调节的时机
在注册设备时,thermal_zone_device_register_with_trips
中将tz->poll_queue
的工作函数设置为thermal_zone_device_check
,并且调用thermal_zone_device_update
。
thermal_zone_device_update
最后会通过thermal_zone_device_set_polling
将tz->poll_queue
添加到system_freezable_power_efficient_wq
,而使thermal_zone_device_check
可以周期性执行。
如果sensor有中断信号给到CPU,当温度超过设置的阈值时,会上报中断,通常会在中断服务函数中调用thermal_zone_device_update,来达到温度实时调节的目的。
6.2. 核心函数:thermal_zone_device_update
thermal_zone_device_update是温度监测和调节的核心函数。
1void thermal_zone_device_update(struct thermal_zone_device *tz,
2 enum thermal_notify_event event)
3{
4 int count;
5
6 if (atomic_read(&in_suspend))
7 return;
8
9 if (WARN_ONCE(!tz->ops->get_temp, "'%s' must not be called without "
10 "'get_temp' ops set\n", __func__))
11 return;
12
13 mutex_lock(&tz->lock);
14
15 if (!thermal_zone_device_is_enabled(tz))
16 goto out;
17
18 update_temperature(tz);
19
20 __thermal_zone_set_trips(tz);
21
22 tz->notify_event = event;
23
24 for (count = 0; count < tz->num_trips; count++)
25 handle_thermal_trip(tz, count);
26
27 monitor_thermal_zone(tz);
28out:
29 mutex_unlock(&tz->lock);
30}
6.2.1. update_temperature
调用sensor的get_temp函数读取温度,并保存到thermal_zone_device.temperature
,thermal_zone_device.temperature
的值记录到thermal_zone_device.last_temperature
。
6.2.2. __thermal_zone_set_trips
用于设置触发中断的温度阈值。
6.2.3. handle_thermal_trip
handle_thermal_trip主要工作是对thermal_zone_device.temperature
与各个阈值温度进行对比,并根据阈值温度的类型执行相应操作,最后调用monitor_thermal_zone来决定下一次执行tz->poll_queue
的时机。
阈值温度的类型由enum thermal_trip_type
描述
thermal_trip_type | 温度调节策略 |
---|---|
THERMAL_TRIP_ACTIVE, THERMAL_TRIP_PASSIVE | 由governor指定的策略来调节 |
THERMAL_TRIP_HOT | 执行thermal_zone_device_ops的notify函数(可能为NULL) |
THERMAL_TRIP_CRITICAL | 执行poweroff_work指定的工作 |
handle_thermal_trip主要流程如下:
- 通过netlink通知温度变化趋势:
thermal_notify_tz_trip_up/down
- 对于类型为CRITICAL或HOT,调用handle_critical_trips,否则调用handle_non_critical_trips
- handle_critical_trips会通过
tz->ops->notify
发送通知,如果是CRITICAL,则会调用orderly_poweroff,执行poweroff_work指定的工作。 - 调用thermal_governar的throttle函数,如果thermal_zone_device没有指定thermal_governor,则使用def_governor
handle_thermal_trip及后续相关函数会用到thermal_zone_device_ops的一些函数,这些是在注册设备时指定的,对于of_parse_thermal_zones注册的设备,使用的操作函数集合如下。除了OF系列函数外,还有ACPI等系列函数。
6.2.4. monitor_thermal_zone
决定下一次执行tz->poll_queue
的时机。
7. sysfs下的文件
thermal相关文件路径位于/sys/devices/virtual/thermal/
,/sys/class/thermal/
的也会有这些文件的链接。
7.1. thermal_zoneX目录
包含了struct thermal_zone_params
的参数
file | perm | desc |
---|---|---|
available_policies | r | 可选的温度调节策略 |
emul_temp | w | 模拟设置thermal的温度,单位毫摄氏度,设置后和实际达到这个温度同效果。值为0时读取的是真正的温度 |
integral_cutoff | rw | 用于power_alloctor策略,误差不再累积的阈值 |
k_d | rw | 用于power_alloctor策略,PID控制器的微分参数 |
k_i | rw | 用于power_alloctor策略,PID控制器的积分参数 |
k_po | rw | 用于power_alloctor策略,超调时PID控制器的比例参数 |
k_pu | rw | 用于power_alloctor策略,下冲时PID控制器的比例参数 |
mode | rw | 此thermal-zone是否使能了,若是为disabled,对其sys文件的操作不生效,可以echo enabled使能 |
offset | rw | 线性温度调节曲线的偏移,Used by thermal zone drivers (default 0) |
passive | rw | 用于step-wise,如果大于0,打开所有ACPI处理器冷却设备的温度 |
policy | rw | 当前使用的governor,也可以通过写入来修改策略 |
slope | rw | 线性温度调节曲线的斜率,Used by thermal zone drivers |
sustainable_power | rw | 该thermal-zone可耗散的可持续功率(热量),单位mW |
temp | r | 当前温度,向emul_temp中写的值也体现在这里 |
trip_point_0_hyst | r | 滞后温度,来自设备树trips下的子节点0的hysteresis字段 |
trip_point_0_temp | r | 触发温度,来自设备树trips下的子节点0的temperature字段 |
trip_point_0_type | r | 触发温度类型,来自设备树trips下的子节点0的type字段 |
trip_point_N_xxx | r | 来自设备树trips下的子节点N的字段 |
type | r | 该thermal-zone的名称,对应于设备树thermal-zones下子节点的名字 |
7.2. cooling_deviceX目录
file | perm | desc |
---|---|---|
cur_state | rw | 当前的cooling state |
max_state | r | 最大的cooling state |
type | r | cooling device的名称 |
stats/reset | w | 对统计状态进行复位 |
stats/time_in_state_ms | r | 在每个state下停留的时间 |
stats/total_trans | r | 不同state之间转换的次数 |
stats/trans_table | r | 记录各个state状态转换表 |