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实现的工作比较简单

  1. 如果使能了CONFIG_THERMAL_NETLINK,就注册thermal_gnl_family。
  2. 注册governor,并设置def_governor。
  3. 注册thermal_class。
  4. 注册thermal_pm_nb通知链。

thermal_init

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节点。

thermal_zone_device

3.1. 主要的dts属性

主要的属性描述参考Documentation/devicetree/bindings/thermal/下的几个文件。

1thermal-cooling-devices.yaml
2thermal-idle.yaml
3thermal-sensor.yaml
4thermal-zones.yaml

thermal_register

在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

thermal_cooling_device_flow

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_pollingtz->poll_queue添加到system_freezable_power_efficient_wq,而使thermal_zone_device_check可以周期性执行。

如果sensor有中断信号给到CPU,当温度超过设置的阈值时,会上报中断,通常会在中断服务函数中调用thermal_zone_device_update,来达到温度实时调节的目的。 thermal_poll

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.temperaturethermal_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主要流程如下:

  1. 通过netlink通知温度变化趋势:thermal_notify_tz_trip_up/down
  2. 对于类型为CRITICAL或HOT,调用handle_critical_trips,否则调用handle_non_critical_trips
  3. handle_critical_trips会通过tz->ops->notify发送通知,如果是CRITICAL,则会调用orderly_poweroff,执行poweroff_work指定的工作。
  4. 调用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状态转换表