通用散热 Sysfs 驱动程序指南

作者:Sujith Thomas <sujith.thomas@intel.com>,Zhang Rui <rui.zhang@intel.com>

版权所有 (c) 2008 英特尔公司

0. 简介

通用散热 sysfs 提供一组接口,用于散热区域设备(传感器)和散热设备(风扇、处理器...)向散热管理解决方案注册并成为其中的一部分。

本指南侧重于使新的散热区域和散热设备能够参与散热管理。此解决方案与平台无关,任何类型的散热区域设备和散热设备都应该能够使用该基础设施。

散热 sysfs 驱动程序的主要任务是将散热区域属性以及散热设备属性公开给用户空间。智能散热管理应用程序可以根据散热区域属性(当前温度和跳变点温度)的输入来做出决策并节流适当的设备。

  • [0-*]表示从 0 开始的任何正数

  • [1-*]表示从 1 开始的任何正数

1. 散热 sysfs 驱动程序接口函数

1.1 散热区域设备接口

struct thermal_zone_device *
thermal_zone_device_register_with_trips(const char *type,
                                const struct thermal_trip *trips,
                                int num_trips, void *devdata,
                                const struct thermal_zone_device_ops *ops,
                                const struct thermal_zone_params *tzp,
                                unsigned int passive_delay,
                                unsigned int polling_delay)

此接口函数将新的散热区域设备(传感器)添加到 /sys/class/thermal 文件夹,如 thermal_zone[0-*]。它尝试同时绑定所有已注册的散热设备。

type

散热区域类型。

trips

此散热区域的跳变点表。

devdata

设备私有数据

ops

散热区域设备回调。

.should_bind

检查给定的散热设备是否应绑定到此散热区域中的给定跳变点。

.get_temp

获取散热区域的当前温度。

.set_trips

设置跳变点窗口。每当更新当前温度时,都会找到紧邻当前温度下方和上方的跳变点。

.change_mode

更改散热区域的模式(启用/禁用)。

.set_trip_temp

设置给定跳变点的温度。

.get_crit_temp

获取此散热区域的临界温度。

.set_emul_temp

设置仿真温度,这有助于调试不同的阈值温度点。

.get_trend

获取最近区域温度变化的趋势。

.hot

热跳变点跨越处理程序。

.critical

临界跳变点跨越处理程序。

tzp

散热区域平台参数。

passive_delay

执行被动散热时,两次轮询之间等待的毫秒数。

polling_delay

在检查是否已跨越跳变点时,两次轮询之间等待的毫秒数(对于中断驱动系统,为 0)。

void thermal_zone_device_unregister(struct thermal_zone_device *tz)

此接口函数删除散热区域设备。它会从 /sys/class/thermal 文件夹中删除相应的条目,并取消绑定其使用的所有散热设备。

struct thermal_zone_device
*thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
                     void *data,
                     const struct thermal_zone_of_device_ops *ops)

此接口将新传感器添加到 DT 散热区域。此函数将搜索设备树中描述的散热区域列表,并查找将 dev->of_node 指向的传感器设备作为温度提供者的区域。对于指向传感器节点的区域,该传感器将被添加到 DT 散热区域设备。

此接口的参数为

dev

传感器设备节点,其中 dev->of_node 中包含有效的节点指针。

sensor_id

传感器标识符,以防传感器 IP 有多个传感器

data

私有指针(由调用者拥有),在需要读取温度时会将其传递回。

ops

struct thermal_zone_of_device_ops *.

get_temp

指向读取传感器温度的函数的指针。这是传感器驱动程序提供的强制回调。

set_trips

指向设置温度窗口的函数的指针。当离开此窗口时,驱动程序必须通过 thermal_zone_device_update 通知散热核心。

get_trend

指向读取传感器温度趋势的函数的指针。

set_emul_temp

指向设置传感器仿真温度的函数的指针。

散热区域温度由 thermal_zone_of_device_ops 的 get_temp() 函数指针提供。调用时,它会将私有指针 @data 返回。

如果失败,则返回错误指针,否则返回有效的散热区域设备句柄。调用者应使用 IS_ERR() 检查返回的句柄,以查找是否成功。

void thermal_zone_of_sensor_unregister(struct device *dev,
                                       struct thermal_zone_device *tzd)

此接口从 DT 散热区域取消注册传感器,该传感器已由接口 thermal_zone_of_sensor_register() 成功添加。此函数从使用 thermal_zone_of_sensor_register() 接口注册的散热区域设备中删除传感器回调和私有数据。它还将通过删除 .get_temp() 和 get_trend() 散热区域设备回调来使区域静默。

struct thermal_zone_device
*devm_thermal_zone_of_sensor_register(struct device *dev,
                      int sensor_id,
                      void *data,
                      const struct thermal_zone_of_device_ops *ops)

此接口是 thermal_zone_of_sensor_register() 的资源管理版本。

第 1.1.3 节中描述的 thermal_zone_of_sensor_register() 的所有详细信息都适用于此处。

使用此接口注册传感器的优点是不需要在错误路径或驱动程序取消绑定期间显式调用 thermal_zone_of_sensor_unregister(),因为这是由驱动程序资源管理器完成的。

void devm_thermal_zone_of_sensor_unregister(struct device *dev,
                                struct thermal_zone_device *tzd)

此接口是 thermal_zone_of_sensor_unregister() 的资源管理版本。第 1.1.4 节中描述的 thermal_zone_of_sensor_unregister() 的所有详细信息都适用于此处。通常,不需要调用此函数,资源管理代码将确保释放该资源。

int thermal_zone_get_slope(struct thermal_zone_device *tz)

此接口用于读取散热区域设备的斜率属性值,这对于平台驱动程序进行温度计算可能很有用。

int thermal_zone_get_offset(struct thermal_zone_device *tz)

此接口用于读取散热区域设备的偏移属性值,这对于平台驱动程序进行温度计算可能很有用。

1.2 散热设备接口

struct thermal_cooling_device
*thermal_cooling_device_register(char *name,
                void *devdata, struct thermal_cooling_device_ops *)

此接口函数将新的散热设备(风扇/处理器/...)添加到 /sys/class/thermal/ 文件夹,如 cooling_device[0-*]。它尝试同时将其自身绑定到所有已注册的散热区域设备。

name

散热设备名称。

devdata

设备私有数据。

ops

散热设备回调。

.get_max_state

获取散热设备的最大节流状态。

.get_cur_state

获取冷却设备当前请求的节流状态。

.set_cur_state

设置冷却设备当前的节流状态。

void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

此接口函数移除热冷却设备。它会从 /sys/class/thermal 文件夹中删除相应的条目,并解除自身与所有使用它的热区域设备的绑定。

1.4 热区域参数

struct thermal_zone_params

此结构定义了热区域的平台级参数。每个热区域的这些数据应来自平台层。这是一个可选功能,某些平台可以选择不提供此数据。

.governor_name

用于此区域的热调速器名称

.no_hwmon

一个布尔值,用于指示是否需要热到 hwmon sysfs 接口。当 no_hwmon == false 时,将创建一个 hwmon sysfs 接口。当 no_hwmon == true 时,将不执行任何操作。如果 thermal_zone_params 为 NULL,将创建 hwmon 接口(为了向后兼容)。

2. sysfs 属性结构

RO

只读值

WO

只写值

RW

读/写值

热 sysfs 属性将表示在 /sys/class/thermal 下。如果 hwmon 已编译或构建为模块,则 hwmon sysfs I/F 扩展也可在 /sys/class/hwmon 下使用。

热区域设备 sys I/F,一旦注册就创建

/sys/class/thermal/thermal_zone[0-*]:
  |---type:                   Type of the thermal zone
  |---temp:                   Current temperature
  |---mode:                   Working mode of the thermal zone
  |---policy:                 Thermal governor used for this zone
  |---available_policies:     Available thermal governors for this zone
  |---trip_point_[0-*]_temp:  Trip point temperature
  |---trip_point_[0-*]_type:  Trip point type
  |---trip_point_[0-*]_hyst:  Hysteresis value for this trip point
  |---emul_temp:              Emulated temperature set node
  |---sustainable_power:      Sustainable dissipatable power
  |---k_po:                   Proportional term during temperature overshoot
  |---k_pu:                   Proportional term during temperature undershoot
  |---k_i:                    PID's integral term in the power allocator gov
  |---k_d:                    PID's derivative term in the power allocator
  |---integral_cutoff:        Offset above which errors are accumulated
  |---slope:                  Slope constant applied as linear extrapolation
  |---offset:                 Offset constant applied as linear extrapolation

热冷却设备 sys I/F,一旦注册就创建

/sys/class/thermal/cooling_device[0-*]:
  |---type:                   Type of the cooling device(processor/fan/...)
  |---max_state:              Maximum cooling state of the cooling device
  |---cur_state:              Current cooling state of the cooling device
  |---stats:                  Directory containing cooling device's statistics
  |---stats/reset:            Writing any value resets the statistics
  |---stats/time_in_state_ms: Time (msec) spent in various cooling states
  |---stats/total_trans:      Total number of times cooling state is changed
  |---stats/trans_table:      Cooling state transition table

然后,接下来的两个动态属性会成对创建/删除。它们表示热区域及其关联的冷却设备之间的关系。

/sys/class/thermal/thermal_zone[0-*]:
  |---cdev[0-*]:              [0-*]th cooling device in current thermal zone
  |---cdev[0-*]_trip_point:   Trip point that cdev[0-*] is associated with
  |---cdev[0-*]_weight:       Influence of the cooling device in
                              this thermal zone

除了热区域设备 sysfs I/F 和冷却设备 sysfs I/F 之外,通用热驱动程序还会为每种类型的热区域设备创建一个 hwmon sysfs I/F。例如,通用热驱动程序注册一个 hwmon 类设备,并为所有已注册的 ACPI 热区域构建相关的 hwmon sysfs I/F。

有关热区域和冷却设备属性的详细信息,请阅读 Documentation/ABI/testing/sysfs-class-thermal。

/sys/class/hwmon/hwmon[0-*]:
  |---name:                   The type of the thermal zone devices
  |---temp[1-*]_input:        The current temperature of thermal zone [1-*]
  |---temp[1-*]_critical:     The critical trip point of thermal zone [1-*]

有关其他信息,请阅读sysfs 文件的命名和数据格式标准

3. 一个简单的实现

ACPI 热区域可能支持多个跳变点,如临界、热、被动、主动。如果 ACPI 热区域同时支持临界、被动、主动[0] 和 主动[1],它可能会将自身注册为具有总共 4 个跳变点的 thermal_zone_device (thermal_zone1)。它有一个处理器和一个风扇,它们都注册为 thermal_cooling_device。两者都被认为在冷却热区域方面具有相同的效果。

如果处理器在 _PSL 方法中列出,并且风扇在 _AL0 方法中列出,则 sys I/F 结构将像这样构建

/sys/class/thermal:
 |thermal_zone1:
   |---type:                   acpitz
   |---temp:                   37000
   |---mode:                   enabled
   |---policy:                 step_wise
   |---available_policies:     step_wise fair_share
   |---trip_point_0_temp:      100000
   |---trip_point_0_type:      critical
   |---trip_point_1_temp:      80000
   |---trip_point_1_type:      passive
   |---trip_point_2_temp:      70000
   |---trip_point_2_type:      active0
   |---trip_point_3_temp:      60000
   |---trip_point_3_type:      active1
   |---cdev0:                  --->/sys/class/thermal/cooling_device0
   |---cdev0_trip_point:       1       /* cdev0 can be used for passive */
   |---cdev0_weight:           1024
   |---cdev1:                  --->/sys/class/thermal/cooling_device3
   |---cdev1_trip_point:       2       /* cdev1 can be used for active[0]*/
   |---cdev1_weight:           1024

 |cooling_device0:
   |---type:                   Processor
   |---max_state:              8
   |---cur_state:              0

 |cooling_device3:
   |---type:                   Fan
   |---max_state:              2
   |---cur_state:              0

/sys/class/hwmon:
 |hwmon0:
   |---name:                   acpitz
   |---temp1_input:            37000
   |---temp1_crit:             100000

4. 导出符号 API

4.1. get_tz_trend

此函数返回热区域的趋势,即热区域温度的变化率。理想情况下,热传感器驱动程序应该实现回调。如果它们没有实现,则热框架会通过比较先前和当前的温度值来计算趋势。

4.2. thermal_cdev_update

此函数用作设置冷却设备状态的仲裁器。如果可能,它会将冷却设备设置为最深的冷却状态。

5. thermal_emergency_poweroff

在临界跳变温度超过的事件中,热框架会通过调用 hw_protection_shutdown() 关闭系统。hw_protection_shutdown() 首先尝试执行有序关机,但在接受延迟后,它会继续执行强制断电或作为最后的手段进行紧急重启。

应仔细分析延迟,以便为有序关机提供足够的时间。

如果延迟设置为 0,则不支持紧急断电。因此,一个经过仔细分析的非零正值对于触发紧急断电是必须的。