温控daemon(三)sensor初始化

既上一篇博客继续分析main函数,上一篇博客我们分析了devices_init device的初始化,这篇博客先是分析保持KTM工作,后面主要分析sensor的初始化,。

1. 保持KTM工作

我们先来看如下,先是创建了一个kernel的client,然后因为有kernel 的device,所以会调用device_clnt_request函数

	kernel_dev = devices_manager_reg_clnt("kernel");//创建一个kernel device的client
	if (kernel_dev == NULL) {
		msg("%s Failed to create kernel device handle\n", __func__);
	} else {
		req.value = 1;//有kernel device
		device_clnt_request(kernel_dev, &req);
	}

上一篇博客我们分析过device_clnt_reques函数,这里传进来的device的type不一样我们再来分析下。kernel的device的type是DEVICE_GENERIC_TYPE,所以调用了devices_manager_set_lvl函数

int device_clnt_request(device_clnt_handle clnt, union device_request *req)
{
	struct devices_manager_dev *dev_mgr = NULL;
	struct device_clnt   *client = clnt;
	int ret_val = 0;

	if ((client == NULL) || (req == NULL)) {
		msg("%s: Invalid args.\n", __func__);
		return -(EINVAL);
	}

	ret_val = validate_clnt(client);//验证client,就是遍历device的list看每个device的client有没有这个client
	if (ret_val != 0)
		return ret_val;

	dev_mgr = client->dev_mgr;

	switch (dev_mgr->dev_info.dev_type) {
	case DEVICE_GENERIC_TYPE://kernel的device的type为这个
		ret_val = devices_manager_set_lvl(dev_mgr, client, req->value);
		break;
	case DEVICE_OP_VALUE_TYPE:
		ret_val = devices_manager_set_op_value(dev_mgr, client,
						       req->value);
		break;
	case DEVICE_DIRECT_ACTION_TYPE:
		ret_val = devices_manager_set_direct_action(dev_mgr, client,
							    req);
		break;
	default:
		dbgmsg("%s: Unhandled dev_type %d", __func__,
		       dev_mgr->dev_info.dev_type);
		break;
	}
	return ret_val;
}

devices_manager_set_lvl函数设置了client的request.value的值,然后调用了update_dev_state来更新device的state。

static int devices_manager_set_lvl(struct devices_manager_dev *dev_mgr,
				   struct device_clnt *client, int lvl)
{
	lvl = MIN(lvl, (int)(dev_mgr->dev_info.num_of_levels - 1));
	lvl = MAX(lvl, (int)(dev_mgr->dev_info.min_lvl));

	pthread_mutex_lock(&clnt_mtx);
	client->request.value = lvl;
	client->request_active = 1;
	pthread_mutex_unlock(&clnt_mtx);
	dbgmsg("%s: DEV %s, lvl %d\n", __func__,
	       dev_mgr->dev_info.name, lvl);
	update_dev_state(dev_mgr);

	return dev_mgr->active_req.value;;
}

update_dev_state函数上一篇博客已经分析过了,这里我们再来看下这里主要是遍历所有的client找到其最大值然后调用device的action函数。

static int update_dev_state(struct devices_manager_dev *dev_mgr)
{
	union device_request req;
	struct device_clnt *client = dev_mgr->client_list;

	if ((dev_mgr->dev_info.dev_type != DEVICE_GENERIC_TYPE) &&
	    (dev_mgr->dev_info.dev_type != DEVICE_OP_VALUE_TYPE))
		return -(EFAULT);

	pthread_mutex_lock(&clnt_mtx);

	if (dev_mgr->dev_info.dev_type == DEVICE_GENERIC_TYPE) {//kernel的type为这个分支
		/* Start from min level to find the highest existing client request */
		req.value = dev_mgr->dev_info.min_lvl;//device的min_lvl作为初始值

		/* Walk client list to find highest mitigation level */
		while (client != NULL) {
			if (client->request_active)
				req.value = MAX(req.value, client->request.value);//遍历所有的client的req.value取其最大值
			client = client->next_clnt;
		}
	} else if (dev_mgr->dev_info.dev_type == DEVICE_OP_VALUE_TYPE) {
		/* Start from max allowable value find lowest request */
		req.value = dev_mgr->dev_info.max_dev_op_value;

		/* Walk client list to find highest mitigation level */
		while (client != NULL) {
			if (client->request_active)
				req.value = MIN(req.value, client->request.value);
			client = client->next_clnt;
		}
	}

	if (dev_mgr->active_req.value != req.value) {
		dev_mgr->active_req.value = req.value;

		if (dev_mgr->action)
			dev_mgr->action(dev_mgr);//调用device的action函数

		/* Notify clients */
		client = dev_mgr->client_list;
		while (client != NULL) {//如果client有回调,就调用回调
			if (client->cb_func != NULL)
				client->cb_func(client, &req,
						client->cb_usr_data);
			client = client->next_clnt;
		}
	}
	pthread_mutex_unlock(&clnt_mtx);
	return 0;
}

而kernel的action最后调用了kernel_mitigation_request函数

static int kernel_mitigation_action(struct devices_manager_dev *dev_mgr)
{
	return kernel_mitigation_request(dev_mgr->active_req.value);
}

kernel_mitigation_request函数现在的request传入的是1,因此不做操作就是继续保持kernel的KTM工作,而当我们的thermal-engine完全工作后(初始化完成),最后会重新走到这,那时request为0,就会write /sys/module/msm_thermal/parameters/enabled节点为N,接管KTM的工作, 当KTM停止工作时,之前在thermal驱动设置的频率会重置。

int kernel_mitigation_request(int request)
{
	int ret = -1;

	pthread_mutex_lock(&kernel_disable_mtx);

	if (request == 0) {
		/* Disable kernel thermal module and take over */
		write_to_file("/sys/module/msm_thermal/parameters/enabled",
			      "N" , strlen("N") + 1);
		dbgmsg("KERNEL mitigation disabled\n");
	} else
		dbgmsg("KERNEL request to keep mitigation enabled\n");

	pthread_mutex_unlock(&kernel_disable_mtx);
	return ret;
}

2. sensor初始化

这节我们开始分析sensor的初始化,main函数调用了sensors_init函数,这个minimum_mode一般为0,我们的代码在Sensors.c中,这个可以从Android.mk查看。

int sensors_init(int minimum_mode)
{
	int ret_val = 0;
	min_mode = minimum_mode;

	if (!min_mode)
		modem_ts_qmi_init();//这里和modem通信的qmi我们后续分析

	init_sensor_alias();
	parse_thermal_zones();

	/* BCL */
	if (add_tgt_sensors_set(bcl_sensors,
			   ARRAY_SIZE(bcl_sensors)) != 0) {
		msg("%s: Error adding BCL TS\n", __func__);
		ret_val = -(EFAULT);
	}

	return ret_val;
}

2.1 读取每个sensor的信息

我们来看下init_sensor_alias函数,先从节点/sys/module/msm_thermal/sensor_info读取节点信息,然后保存sensor信息到sensors数组中,这个sensors的类型是msm_sensor_info。

static void init_sensor_alias(void)
{
	char buf[MAX_SENSOR_INFO_LEN];
	char *psensor_info = NULL, *psave1 = NULL;

	if (read_line_from_file(SENSOR_INFO_SYSFS, buf,//读取/sys/module/msm_thermal/sensor_info节点信息
			MAX_SENSOR_INFO_LEN) <= 0)
		return;

	psensor_info = strtok_r(buf, " ", &psave1);
	while (psensor_info != NULL && sensor_cnt < MAX_NUM_SENSORS) {
		char *psensor = NULL;
		char *psave2 = NULL;

		psensor = strtok_r(psensor_info, ":", &psave2);
		if ((psensor == NULL) || strlcpy(sensors[sensor_cnt].type,//type
			psensor, MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
			goto next_sensor;

		psensor = strtok_r(NULL, ":", &psave2);
		if ((psensor == NULL) || strlcpy(sensors[sensor_cnt].name,//name
			psensor, MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
			goto next_sensor;

		if (psensor[strlen(psensor) + 1] != ':') {
			psensor = strtok_r(NULL, ":", &psave2);
			if ((psensor == NULL) ||
				strlcpy(sensors[sensor_cnt].alias, psensor,//alias
				MAX_SENSOR_NAME_LEN) >= MAX_SENSOR_NAME_LEN)
					goto next_sensor;
		}

		psensor = strtok_r(NULL, ":", &psave2);
		if (psensor == NULL)
			goto next_sensor;
		sensors[sensor_cnt].scaling_factor =
			(int)strtol( psensor, NULL, 10);
		if (sensors[sensor_cnt].scaling_factor <= 0)//scaling_factor
			sensors[sensor_cnt].scaling_factor = 1;

		sensor_cnt++;
next_sensor:
		psensor_info = strtok_r(NULL, " ", &psave1);
	}
	dbgmsg("%s: sensor_cnt:%d\n", __func__, sensor_cnt);
}

我们来先看下节点/sys/module/msm_thermal/sensor_info节点读取到的信息。以冒号为分割第一个是sensor的type,第二个是sensor的name,第三个是alias,第四个是scaling_factor。

tsens:tsens_tz_sensor0:pop_mem:1 tsens:tsens_tz_sensor1::1 tsens:tsens_tz_sensor2::1 tsens:tsens_tz_sensor3:cpu0-cpu2:1 tsens:tsens_tz_sensor4:cpu1-cpu3:1 adc:pa_therm0::1 adc:case_therm::1 alarm:pm8909_tz::1000 adc:xo_therm::1 adc:xo_therm_buf::1

2.2 创建sensor

创建sensor有两种方法,一种读取sys/devices/vitual/thermal下的设备创建,另一种可以直接做一个sensor_info的数组,直接遍历数组创建sensor。

2.2.1 读取thermal节点创建sensor

再来看看parse_thermal_zones函数,这个函数主要看/sys/devices/virtual/thermal下面每个目录下的type 是否和我们前面保存的sensors数组中的sensor的name一样,不一样我们直接跳过。一样的话,我们在根据这个sensor的type调用不同的函数。

static void parse_thermal_zones(void)
{
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值