Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0fc4f38 authored by Manaf Meethalavalappu Pallikunhi's avatar Manaf Meethalavalappu Pallikunhi Committed by Gerrit - the friendly Code Review server
Browse files

msm: thermal: Fix potential memory leak in sensor manager API in KTM



Cancel sensor trip for both high and low thresholds and fix memory
leak in sensor_mgr_remove_threshold API. Modify sensor manager APIs
to use client device to allocate/release memory for thresholds
using devm_kzalloc and devm_kfree.

Change-Id: Icf3b0253d72441e192be5f87c04bdf94799bb036
Signed-off-by: default avatarManaf Meethalavalappu Pallikunhi <manafm@codeaurora.org>
parent b754a2a9
Loading
Loading
Loading
Loading
+46 −35
Original line number Diff line number Diff line
@@ -3856,14 +3856,15 @@ static int msm_thermal_notify(enum thermal_trip_type type, int temp, void *data)
	return 0;
}

int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
int sensor_mgr_init_threshold(struct device *dev,
	struct threshold_info *thresh_inp,
	int sensor_id, int32_t high_temp, int32_t low_temp,
	void (*callback)(struct therm_threshold *))
{
	int ret = 0, i;
	struct therm_threshold *thresh_ptr;

	if (!callback || !thresh_inp
	if (!dev || !callback || !thresh_inp
		|| sensor_id == -ENODEV) {
		pr_err("Invalid input\n");
		ret = -EINVAL;
@@ -3874,15 +3875,17 @@ int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
		goto init_thresh_exit;
	}

	mutex_lock(&threshold_mutex);
	thresh_inp->thresh_ct = (sensor_id == MONITOR_ALL_TSENS) ?
						max_tsens_num : 1;
	thresh_inp->thresh_triggered = false;
	thresh_inp->thresh_list = kzalloc(sizeof(struct therm_threshold) *
	thresh_inp->thresh_list = devm_kzalloc(dev,
					sizeof(struct therm_threshold) *
					thresh_inp->thresh_ct, GFP_KERNEL);
	if (!thresh_inp->thresh_list) {
		pr_err("kzalloc failed for thresh\n");
		ret = -ENOMEM;
		goto init_thresh_exit;
		goto init_thresh_unlock;
	}

	thresh_ptr = thresh_inp->thresh_list;
@@ -3922,26 +3925,34 @@ int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
		thresh_ptr->threshold[0].data =
		thresh_ptr->threshold[1].data = (void *)thresh_ptr;
	}
	mutex_lock(&threshold_mutex);
	list_add_tail(&thresh_inp->list_ptr, &thresholds_list);

init_thresh_unlock:
	mutex_unlock(&threshold_mutex);

init_thresh_exit:
	return ret;
}

void sensor_mgr_remove_threshold(struct threshold_info *thresh_inp)
void sensor_mgr_remove_threshold(struct device *dev,
			struct threshold_info *thresh_inp)
{
	int i;
	struct therm_threshold *thresh_ptr;

	mutex_lock(&threshold_mutex);
	for (i = 0; i < thresh_inp->thresh_ct; i++) {
		thresh_ptr = &thresh_inp->thresh_list[i];
		thresh_ptr->trip_triggered = -1;
		sensor_cancel_trip(thresh_ptr->sensor_id,
				thresh_ptr->threshold);
				&thresh_ptr->threshold[0]);
		sensor_cancel_trip(thresh_ptr->sensor_id,
				&thresh_ptr->threshold[1]);
	}
	mutex_lock(&threshold_mutex);
	devm_kfree(dev, thresh_inp->thresh_list);
	thresh_inp->thresh_list = NULL;
	thresh_inp->thresh_ct = 0;
	thresh_inp->thresh_triggered = false;
	list_del(&thresh_inp->list_ptr);
	mutex_unlock(&threshold_mutex);
}
@@ -4991,7 +5002,8 @@ static int probe_vdd_mx(struct device_node *node,
		goto read_node_done;
	}

	ret = sensor_mgr_init_threshold(&thresh[MSM_VDD_MX_RESTRICTION],
	ret = sensor_mgr_init_threshold(&pdev->dev,
			&thresh[MSM_VDD_MX_RESTRICTION],
			MONITOR_ALL_TSENS,
			data->vdd_mx_temp_degC + data->vdd_mx_temp_hyst_degC,
			data->vdd_mx_temp_degC, vdd_mx_notify);
@@ -5100,7 +5112,8 @@ static int probe_vdd_rstr(struct device_node *node,
					ret);
			goto read_node_fail;
		}
		ret = sensor_mgr_init_threshold(&thresh[MSM_VDD_RESTRICTION],
		ret = sensor_mgr_init_threshold(&pdev->dev,
			&thresh[MSM_VDD_RESTRICTION],
			MONITOR_ALL_TSENS,
			data->vdd_rstr_temp_hyst_degC, data->vdd_rstr_temp_degC,
			vdd_restriction_notify);
@@ -5275,7 +5288,8 @@ static int probe_ocr(struct device_node *node, struct msm_thermal_data *data,
		}
	}

	ret = sensor_mgr_init_threshold(&thresh[MSM_OCR], data->ocr_sensor_id,
	ret = sensor_mgr_init_threshold(&pdev->dev,
		&thresh[MSM_OCR], data->ocr_sensor_id,
		data->ocr_temp_degC,
		data->ocr_temp_degC - data->ocr_temp_hyst_degC,
		ocr_notify);
@@ -5509,7 +5523,8 @@ static int probe_gfx_phase_ctrl(struct device_node *node,
		goto probe_gfx_crit;
	}

	ret = sensor_mgr_init_threshold(&thresh[MSM_GFX_PHASE_CTRL_WARM],
	ret = sensor_mgr_init_threshold(&pdev->dev,
		&thresh[MSM_GFX_PHASE_CTRL_WARM],
		data->gfx_sensor,
		data->gfx_phase_warm_temp_degC, data->gfx_phase_warm_temp_degC -
		data->gfx_phase_warm_temp_hyst_degC,
@@ -5535,7 +5550,8 @@ probe_gfx_crit:
	if (ret)
		goto probe_gfx_exit;

	ret = sensor_mgr_init_threshold(&thresh[MSM_GFX_PHASE_CTRL_HOT],
	ret = sensor_mgr_init_threshold(&pdev->dev,
		&thresh[MSM_GFX_PHASE_CTRL_HOT],
		data->gfx_sensor,
		data->gfx_phase_hot_temp_degC, data->gfx_phase_hot_temp_degC -
		data->gfx_phase_hot_temp_hyst_degC,
@@ -5602,7 +5618,8 @@ static int probe_cx_phase_ctrl(struct device_node *node,
	if (ret)
		goto probe_cx_exit;

	ret = sensor_mgr_init_threshold(&thresh[MSM_CX_PHASE_CTRL_HOT],
	ret = sensor_mgr_init_threshold(&pdev->dev,
		&thresh[MSM_CX_PHASE_CTRL_HOT],
		MONITOR_ALL_TSENS,
		data->cx_phase_hot_temp_degC, data->cx_phase_hot_temp_degC -
		data->cx_phase_hot_temp_hyst_degC,
@@ -5636,7 +5653,8 @@ static int probe_therm_reset(struct device_node *node,
	if (ret)
		goto PROBE_RESET_EXIT;

	ret = sensor_mgr_init_threshold(&thresh[MSM_THERM_RESET],
	ret = sensor_mgr_init_threshold(&pdev->dev,
		&thresh[MSM_THERM_RESET],
		MONITOR_ALL_TSENS,
		data->therm_reset_temp_degC, data->therm_reset_temp_degC - 10,
		therm_reset_notify);
@@ -5827,41 +5845,34 @@ static int msm_thermal_dev_exit(struct platform_device *inp_dev)
		debugfs_remove_recursive(msm_therm_debugfs->parent);
	msm_thermal_ioctl_cleanup();
	if (thresh) {
		if (vdd_rstr_enabled) {
			sensor_mgr_remove_threshold(
		if (therm_reset_enabled)
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_THERM_RESET]);
		if (vdd_rstr_enabled)
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_VDD_RESTRICTION]);
			kfree(thresh[MSM_VDD_RESTRICTION].thresh_list);
		}
		if (cx_phase_ctrl_enabled) {
			sensor_mgr_remove_threshold(
		if (cx_phase_ctrl_enabled)
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_CX_PHASE_CTRL_HOT]);
			kfree(thresh[MSM_CX_PHASE_CTRL_HOT].thresh_list);
		}
		if (gfx_warm_phase_ctrl_enabled) {
			sensor_mgr_remove_threshold(
		if (gfx_warm_phase_ctrl_enabled)
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_GFX_PHASE_CTRL_WARM]);
			kfree(thresh[MSM_GFX_PHASE_CTRL_WARM].thresh_list);
		}
		if (gfx_crit_phase_ctrl_enabled) {
			sensor_mgr_remove_threshold(
		if (gfx_crit_phase_ctrl_enabled)
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_GFX_PHASE_CTRL_HOT]);
			kfree(thresh[MSM_GFX_PHASE_CTRL_HOT].thresh_list);
		}
		if (ocr_enabled) {
			for (i = 0; i < ocr_rail_cnt; i++)
				kfree(ocr_rails[i].attr_gp.attrs);
			kfree(ocr_rails);
			ocr_rails = NULL;
			sensor_mgr_remove_threshold(
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_OCR]);
			kfree(thresh[MSM_OCR].thresh_list);
		}
		if (vdd_mx_enabled) {
			kfree(mx_kobj);
			kfree(mx_attr_group.attrs);
			sensor_mgr_remove_threshold(
			sensor_mgr_remove_threshold(&inp_dev->dev,
				&thresh[MSM_VDD_MX_RESTRICTION]);
			kfree(thresh[MSM_VDD_MX_RESTRICTION].thresh_list);
		}
		kfree(thresh);
		thresh = NULL;
+4 −4
Original line number Diff line number Diff line
@@ -1579,7 +1579,7 @@ static int supply_lm_therm_device_init(struct platform_device *pdev,
		}
	}

	ret = sensor_mgr_init_threshold(
	ret = sensor_mgr_init_threshold(&pdev->dev,
				&supply_lm_therm_thresh[THERM_HOT - 1],
				MONITOR_ALL_TSENS,
				supply_lm_data->hot_temp_degC,
@@ -1592,7 +1592,7 @@ static int supply_lm_therm_device_init(struct platform_device *pdev,
		goto therm_exit;
	}

	ret = sensor_mgr_init_threshold(
	ret = sensor_mgr_init_threshold(&pdev->dev,
				&supply_lm_therm_thresh[THERM_VERY_HOT - 1],
				MONITOR_ALL_TSENS,
				supply_lm_data->very_hot_temp_degC,
@@ -1653,9 +1653,9 @@ static void supply_lm_therm_cleanup(struct platform_device *pdev,
		return;

	if (supply_lm_therm_thresh) {
		sensor_mgr_remove_threshold(
		sensor_mgr_remove_threshold(&pdev->dev,
			&supply_lm_therm_thresh[THERM_VERY_HOT - 1]);
		sensor_mgr_remove_threshold(
		sensor_mgr_remove_threshold(&pdev->dev,
			&supply_lm_therm_thresh[THERM_HOT - 1]);
		devm_kfree(&pdev->dev, supply_lm_therm_thresh);
		supply_lm_therm_thresh = NULL;
+9 −4
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ extern int msm_thermal_get_cluster_voltage_plan(uint32_t cluster,
 *                             sensor(s) with high and low thresholds and
 *                             threshold callback.
 *
 * @dev: Client device structure.
 * @thresh_inp: Client threshold data structure.
 * @sensor_id: Sensor h/w ID to be monitored. Use MONITOR_ALL_TSENS
 *             to monitor all temperature sensors.
@@ -179,7 +180,8 @@ extern int msm_thermal_get_cluster_voltage_plan(uint32_t cluster,
 * on failure. MACRO IS_HI_THRESHOLD_SET/IS_LOW_THRESHOLD_SET can be used
 * to decipher which threshold being set.
 */
extern int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
extern int sensor_mgr_init_threshold(struct device *dev,
				struct threshold_info *thresh_inp,
				int sensor_id, int32_t high_temp,
				int32_t low_temp,
				void (*callback)(struct therm_threshold *));
@@ -210,9 +212,11 @@ extern int sensor_mgr_set_threshold(uint32_t zone_id,
 *                              removes threshold from sensor manager
 *                              threshold list.
 *
 * @dev: Client device structure.
 * @thresh_inp: The threshold info which needs to be removed.
 */
extern void sensor_mgr_remove_threshold(struct threshold_info *thresh_inp);
extern void sensor_mgr_remove_threshold(struct device *dev,
				struct threshold_info *thresh_inp);
/**
 * devmgr_register_mitigation_client - Register for a device and
 *                                     gets a handle for mitigation.
@@ -284,7 +288,8 @@ static inline int msm_thermal_get_cluster_voltage_plan(uint32_t cluster,
{
	return -ENOSYS;
}
static inline int sensor_mgr_init_threshold(struct threshold_info *thresh_inp,
static inline int sensor_mgr_init_threshold(struct device *dev,
				struct threshold_info *thresh_inp,
				int sensor_id, int32_t high_temp,
				int32_t low_temp,
				void (*callback)(struct therm_threshold *))
@@ -301,7 +306,7 @@ static inline int sensor_mgr_set_threshold(uint32_t zone_id,
{
	return -ENOSYS;
}
static inline void sensor_mgr_remove_threshold(
static inline void sensor_mgr_remove_threshold(struct device *dev,
				struct threshold_info *thresh_inp)
{
}