Linux Thermal 學習筆記


一、thermal 模塊簡介

1. 核心為 thermal_core。可以獲取溫度的設備抽象為 thermal_zone_device, 如Temp Sensor、NTC(板上的熱敏電阻)等。控制溫度的設備抽象為 thermal_cooling_device, 如風扇、CPU、DDR、GPU等。溫控策略抽象為 thermal_governor,比如 step_wise、bang_bang 等。

 

thermal_cooling_device 對應系統實施冷卻措施的驅動,是溫控的執行者。cooling device 維護一個 cooling 等級,即 state,一般 state 越高即系統的冷卻需求越高。cooling device 根據不同等級的冷卻需求進行冷卻行為。cooling device 只根據 state 進行冷卻操作,是實施者,而 state 的計算由 thermal governor 完成。結構 struct cpufreq_cooling_device 和 struct devfreq_cooling_device 作為對 thermal_cooling_device 的擴展,分別主要在 cpufreq_cooling.c 和 devfreq_cooling.c 中使用。

thermal_instance 結構體描述 trip point 與 cooling device 的綁定關系,即當 trip point 觸發后由哪個 cooling device 去實施冷卻措施。每個 trip point 必須與一個 cooling device 綁定,才有實際意義。


一個 Thermal Zone 可以有多個 Cooling 設備;同時還提供一個核心函數 thermal_zone_device_update 作為 Thermal 中斷處理函數和輪詢函數,輪詢時間會根據不同 Trip Delay 調節。模塊流程圖如下:

 流程:

thermal_zone_device_register --> INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check) --> thermal_zone_device_check --> thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED)

讀取 thermal 溫度,然后根據 trip 類型執行 critical 或者 non critical 響應操作。critical 則直接調用 orderly_poweroff; non critical 則調用 governor 的 throttle 函數。

 

2. Thermal Governor(溫控算法)

Thermal Governor即溫控算法,解決溫控發生時,如何選擇 cooling state 的問題,當前可用的governor包括:bang_bang、step_wise、user_space、low_limit、power_allocator

(1) bang_bang governor

由於 bang_bang governor 是用在使用風扇散熱的設備中的算法。首先我們需要確定 throttle 即溫控是否觸發。這包括了兩種情況,第一種為當前溫度大於溫控閾值,第二種為當前溫度小於溫控閾值但是大於滯后溫度(溫控解除溫度),並且是處於降溫的過程中。bang_bang governor的降溫策略跟它的名字一樣簡單,可以用一句話來概括: 當throttle發生,打開風扇;當throttle解除,關閉風扇。

 

(2) step_wise governor

step_wise 算法在計算 target cooling state 的過程中,除了需要知道是否 throttle,還添加了一個 trend 作為參考條。trend 表示溫升趨勢,Linux Thermal Framework 定義了五種 trend type,見 enum thermal_trend,即穩定(THERMAL_TREND_STABLE), 上升(THERMAL_TREND_RAISING), 下降(THERMAL_TREND_DROPPING), 最高溫線(THERMAL_TREND_RAISE_FULL),最低溫線(THERMAL_TREND_DROP_FULL)。

 

step_wise governor 對於 cooling_state 選擇的策略:

a. 當 throttle 發生且溫升趨勢為上升,使用更高一級的 cooling state;
b. 當 throttle 發生且溫升趨勢為下降,不改變 cooling state;
c. 當 throttle 解除且溫升趨勢為下降,不改變 cooling state;
d. 當 throttle 解除且溫升趨勢為上升,使用更低一級的 cooling state;

step_wise governor 是每個輪詢周期逐級提高冷卻狀態,是一種相對溫和的溫控策略。

(3) low_limit governor

移動設備在溫度比較低的情況下同樣會存在諸如無法充電等問題,所以 low_limit governor 應運而生,這個特殊的溫控算法用於低溫環境下的設備加熱。它的溫控策略基本上就是反向的 step_wise,在這里就不進一步展開敘述了,感興趣的同學可以自行查看kernel源碼,內核5.10中已經將其移除。

(4) user_space governor

user_space governor 是通過 uevent 將溫區當前溫度,溫控觸發點等信息上報到用戶空間,由用戶空間軟件制定溫控的策略。

(5) power_allocator governor

power_allocator governor 即 IPA 算法,是由 ARM 在2015年提交及納入 Linux kernel mainline。IPA(Intelligent Power Allocator)模型的核心是利用 PID 控制器,ThermalZone 的溫度作為輸入,可分配功耗值作為輸出,調節 Allocator 的頻率和電壓值。

 

3. 各個governor是通過 __section() 屬性配合鏈接器腳本鏈接到一起的

//drivers/thermal/gov_step_wise.c
THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);

//drivers/thermal/thermal_core.h
#define THERMAL_TABLE_ENTRY(table, name)            \
    static typeof(name) *__thermal_table_entry_##name    \
    __used __section("__" #table "_thermal_table") = &name

#define THERMAL_GOVERNOR_DECLARE(name)    THERMAL_TABLE_ENTRY(governor, name)

//展開后為:
static struct thermal_governor *__thermal_table_entry_thermal_gov_step_wise    \
    __used __section("__governor_thermal_table") = &thermal_gov_step_wise //__section()中應該會自動去掉中間的空格


//include/asm-generic/vmlinux.lds.h
#define THERMAL_TABLE(name)                        \
    . = ALIGN(8);                            \
    __##name##_thermal_table = .;                    \
    KEEP(*(__##name##_thermal_table))                \
    __##name##_thermal_table_end = .;

#define INIT_DATA \
    ...
    THERMAL_TABLE(governor)    \
    ...

//展開后為:
#define THERMAL_TABLE(governor)                        \
    . = ALIGN(8);                            \
    __governor_thermal_table = .;                    \
    KEEP(*(__governor_thermal_table))                \
    __governor_thermal_table_end = .;

使用遍歷方法:

/* Init section thermal table */
extern struct thermal_governor *__governor_thermal_table[];
extern struct thermal_governor *__governor_thermal_table_end[];

#define for_each_governor_table(__governor)        \
    for (__governor = __governor_thermal_table;    __governor < __governor_thermal_table_end;    __governor++)

 

二、設備樹配置

1. 除了SOC里面的溫度傳感器分別監控各個子系統的當前溫度外。同樣在PCB上還包含有多個熱敏電阻(NTC), 這些NTC通過算法的計算后可以獲得手機主板上各個區域的溫度。軟件上將這些 tsensor 及 ntc 等可以獲取溫度的設備描述為 thermal zone, 在代碼中以 dts 的形式來描述。

//thermal_zones 下每一個子節點都是一個 thermal, 在 /sys/class/thermal 下對應一個 thermal_zoneX 目錄,ntc的也在里面。
thermal_zones: thermal-zones {
    ...
    soc_max {
        polling-delay = <0>; /* /* 溫控未發生時(超過閾值時)輪詢周期(ms) */ */
        polling-delay-passive = <0>; /* 溫控發生時(未超過閾值時)的輪詢周期(ms) 配置為0,代表不使用輪詢方式,通過tsensor中斷觸發溫控。*/
        thermal-governor = "step_wise"; /* 補充的,該溫區發生溫控時所使用的算法*/
        thermal-sensors = <&lvts 0>; /* 對應的sensor,表示使用 lvts 這個溫度傳感器的通道0 */

        trips { /* 溫控觸發點 */
            soc_max_crit: soc_max_crit@0 {
                /* 觸發溫度為(116500)/1000 = 116.5 度發生溫控,對應 trip_point_0_temp 文件 */
                temperature = <116500>;
                /* 滯后溫度,表示當下降到(116.5 – 2000/1000) = 114.5 度時解除溫控,對應 trip_point_0_hyst 文件 */
                hysteresis = <2000>;
                /*
                 * "critical"表示觸發溫控后立刻重啟,若配置為”passive”,表示當溫控發生后由governor控制,
                 * 輪詢周期改為使用 polling-delay-passive,對應 trip_point_0_type 文件 
                 */
                type = "critical"; 
            };
        };
    };
    ...
}

trips 即觸發點,每個 thermal zone 可以維護多個 trip point,其 type 為 trip point類型,沿襲PC散熱方式,分為四種類型 passive、active、hot、critical,在內核中由 enum thermal_trip_type 描述,若是 critical,溫度觸發后直接觸發重啟,非 critical 類型由 governor 的溫控策略來降溫。

 

2. 現在我們已經將 tsensor 跟 NTC 以 thermal_zone 的形式注冊到系統中,可以實時的監控設備各個子系統的發熱狀況。當溫度超過所設閾值時,將會上報中斷,接下來就是冷卻設備起作用的時刻了。這些通過控制自己的狀態達到降溫效果的設備,操作系統將其抽象為 cooling_device(冷卻設備)。像 cpufreq, devfreq 等driver在初始化的時候會調用 of_thermal.c 提供的接口在 thermal_core 中注冊 cooling device。

gpu2 {
    polling-delay = <100>; /* milliseconds */
    polling-delay-passive = <12>; /* milliseconds */
    thermal-sensors = <&lvts 14>;

    trips {
        gpu_throttle: trip-point@0 {
            temperature = <95000>;
            hysteresis = <2000>;
            type = "passive";
        };
    };
    /* 該溫區對應到的冷卻設備列表 */
    cooling-maps {
        map0 {
            /* 該冷卻設備對應的溫區溫控觸發點 */
            trip = <&gpu_throttle>;
            /* 對應的真正執行冷卻操作的設備及最大/最小狀態,格式為< phandle of device, min_state,max_state> */
            cooling-device = <&mali THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
            contribution = <1024>;
        };
    };
};

注:MTK 5.10內核的 cooling device 沒有再按這個設備樹格式了,檢索 #cooling-cells 來查找 cooling device 的設備樹節點配置。

 

三、文件接口

1. /sys/class/thermal/thermal_zoneX

/sys/class/thermal/thermal_zone0 # ls -l
-r--r--r-- available_policies //可選的溫控governor,如 power_allocator user_space step_wise
--w------- emul_temp //模擬設置thermal的溫度,單位毫攝氏度,設置后 update_temperature()中可獲取到這個溫度,和實際達到這個溫度同效果。只有其為0,讀取的才是真正的溫度值,否則就是echo的模擬值
-rw-r--r-- integral_cutoff
-rw-r--r-- k_d
-rw-r--r-- k_i
-rw-r--r-- k_po
-rw-r--r-- k_pu
-rw-r--r-- mode //此thermalzone是否使能了,若是為disabled,對其sys文件的操作不生效,可以echo enabled使能
-rw-r--r-- offset
-rw-r--r-- passive
-rw-r--r-- policy //當前使用的governor是哪個
-rw-r--r-- slope
-rw-r--r-- sustainable_power
-r--r--r-- temp //該溫區的當前溫度,測試時往 emul_temp 中寫的值也會體現在這里。
-rw-r--r-- trip_point_0_hyst //滯后溫度,來自設備樹 hysteresis 字段,此例中為 2000。有 trips 節點才會有此文件。
-rw-r--r-- trip_point_0_temp //觸發溫度,來自設備樹 temperature字段,此例中為 116500,可以通過sysfs更改。
-r--r--r-- trip_point_0_type //觸發點0的類型,來自設備樹 type 字段,此例中為"critical"
-r--r--r-- type //該溫區的名稱,對應於設備樹 thermal_zones 下子節點的名字,此例中為"soc_max"
-rw-r--r-- uevent

不同 thermal_zoneX 下的文件不完全相同,取決於在設備樹中是否指定了trips成員,以及指定了幾個。

 

2. /sys/class/thermal/cooling_deviceX

/sys/class/thermal/cooling_device0 # ls -l
-rw-r--r-- cur_state //該 cooling_device 的當前 cooling state
-r--r--r-- max_state //該 cooling_device 的最大 cooling state
drwxr-xr-x  stats
-r--r--r-- type //該cooling device的名稱
-rw-r--r-- uevent

/sys/class/thermal/cooling_device0 # ls -l stats/
--w------- reset //對統計狀態進行復位
-r--r--r-- time_in_state_ms //在每個state下停留的時間
-r--r--r-- total_trans //不同state之間轉換的次數
-r--r--r-- trans_table //各個state狀態轉換表,最大只能顯示1個頁的內容

type 為 thermal-cpufreq-X 的 cool device 控制 CPU ClusterX 的頻點,比如向 cur_state 中寫入 max_state 的值,對應Cluster的 scaling_max_freq 文件將顯示被限制到了最小頻點。
type 為 thermal-cpufreq-X 的是通過 cpufreq_cooling.c 注冊的 cool device,type 為 thermal-devfreq-X 的是通過 devfreq_cooling.c 注冊的 cool device。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM