thermal中cool device和zone device的绑定
thermal是linux中温度相关的子模块,其源码在drivers/thermal/。thermal子系统分为thermal zone device和thermal cool device。zone device是获取当前设备温度的设备,例如传感器等。在kernel中用来thermal_zone_device代表zone devie。struct thermal_zone_device {
·
thermal是linux中温度相关的子模块,其源码在drivers/thermal/。thermal子系统分为thermal zone device和thermal cool device。zone device是获取当前设备温度的设备,例如传感器等。
在kernel中用来thermal_zone_device代表zone devie。
struct thermal_zone_device {
int id;
char type[THERMAL_NAME_LENGTH];
struct thermal_zone_device_ops *ops;
struct thermal_zone_params *tzp;
struct thermal_governor *governor;
};
其成员变量thermal_zone_device_ops 代表zone device 获取温度的方法
struct thermal_zone_device_ops {
int (*bind) (struct thermal_zone_device *,
struct thermal_cooling_device *);
int (*unbind) (struct thermal_zone_device *,
struct thermal_cooling_device *);
int (*get_temp) (struct thermal_zone_device *, int *);
int (*set_trips) (struct thermal_zone_device *, int, int);
};
其最终要的成员变量是get_temp,来得到zone device的当前温度
thermal_cooling_device代表降温的手段,对风扇而言就是提高转速,对cpu而言就是降压降频来减少cpu的发热
struct thermal_cooling_device {
const struct thermal_cooling_device_ops *ops;
};
struct thermal_cooling_device_ops {
int (*get_max_state) (struct thermal_cooling_device *, unsigned long *);
int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *);
int (*set_cur_state) (struct thermal_cooling_device *, unsigned long);
};
类似其成员变量thermal_cooling_device_ops 中的set_cur_state代表当前需要降温的等级
还有一个Thermal Governor代表降温的策略。从makefile中可以发现,总共有如下五种Governor
# governors
thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o
thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o
thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o
thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += power_allocator.o
从下面的makefile可以看出thermal的初始化文件是thermal_core.c
thermal_sys-y += thermal_core.o thermal_sysfs.o \
thermal_helpers.o
fs_initcall(thermal_init);
可见开机会通过fs_initcall调用thermal_init。
thermal_init->thermal_register_governors
5中governors 会同时存在系统中
static int __init thermal_register_governors(void)
{
int result;
result = thermal_gov_step_wise_register();
if (result)
return result;
result = thermal_gov_fair_share_register();
if (result)
return result;
result = thermal_gov_bang_bang_register();
if (result)
return result;
result = thermal_gov_user_space_register();
if (result)
return result;
return thermal_gov_power_allocator_register();
}
thermal_init->of_parse_thermal_zones
int __init of_parse_thermal_zones(void)
{
struct device_node *np, *child;
struct __thermal_zone *tz;
struct thermal_zone_device_ops *ops;
np = of_find_node_by_name(NULL, "thermal-zones");
if (!np) {
pr_debug("unable to find thermal zones\n");
return 0; /* Run successfully on systems without thermal DT */
}
for_each_available_child_of_node(np, child) {
struct thermal_zone_device *zone;
struct thermal_zone_params *tzp;
int i, mask = 0;
u32 prop;
//通过devicetree 得到__thermal_zone
tz = thermal_of_build_thermal_zone(child);
if (IS_ERR(tz)) {
pr_err("failed to build thermal zone %s: %ld\n",
child->name,
PTR_ERR(tz));
continue;
}
ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
if (!ops)
goto exit_free;
tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
if (!tzp) {
kfree(ops);
goto exit_free;
}
/* No hwmon because there might be hwmon drivers registering */
tzp->no_hwmon = true;
if (!of_property_read_u32(child, "sustainable-power", &prop))
tzp->sustainable_power = prop;
for (i = 0; i < tz->ntrips; i++)
mask |= 1 << i;
/* these two are left for temperature drivers to use */
tzp->slope = tz->slope;
tzp->offset = tz->offset;
在thermal_zone_device_register->bind_tz->__bind 来让cool device和zone device绑定
zone = thermal_zone_device_register(child->name, tz->ntrips,
mask, tz,
ops, tzp,
tz->passive_delay,
tz->polling_delay);
if (IS_ERR(zone)) {
pr_err("Failed to build %s zone %ld\n", child->name,
PTR_ERR(zone));
kfree(tzp);
kfree(ops);
of_thermal_free_zone(tz);
/* attempting to build remaining zones still */
}
}
of_node_put(np);
return 0;
}
static void __bind(struct thermal_zone_device *tz, int mask,
struct thermal_cooling_device *cdev,
unsigned long *limits,
unsigned int weight)
{
int i, ret;
for (i = 0; i < tz->trips; i++) {
if (mask & (1 << i)) {
unsigned long upper, lower;
upper = THERMAL_NO_LIMIT;
lower = THERMAL_NO_LIMIT;
if (limits) {
lower = limits[i * 2];
upper = limits[i * 2 + 1];
}
//可以看到最终调用thermal_zone_bind_cooling_device来绑定cool device和zone device 省略中间过程的话,可以看到是起始是在注册zone device函数thermal_zone_device_register中调用thermal_zone_bind_cooling_device来绑定cool device.
thermal_zone_device_register->thermal_zone_bind_cooling_device
ret = thermal_zone_bind_cooling_device(tz, i, cdev,
upper, lower,
weight);
if (ret)
print_bind_err_msg(tz, cdev, ret);
}
}
}
更多推荐
已为社区贡献3条内容
所有评论(0)