Commit 6b8249ab authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Zhang Rui
Browse files

drivers: thermal: qcom: tsens: Fix memory leak from qfprom read



memory returned as part of nvmem_read via qfprom_read should be
freed by the consumer once done.
Existing code is not doing it so fix it.

Below memory leak detected by kmemleak
   [<ffffff80088b7658>] kmemleak_alloc+0x50/0x84
    [<ffffff80081df120>] __kmalloc+0xe8/0x168
    [<ffffff80086db350>] nvmem_cell_read+0x30/0x80
    [<ffffff8008632790>] qfprom_read+0x4c/0x7c
    [<ffffff80086335a4>] calibrate_v1+0x34/0x204
    [<ffffff8008632518>] tsens_probe+0x164/0x258
    [<ffffff80084e0a1c>] platform_drv_probe+0x80/0xa0
    [<ffffff80084de4f4>] really_probe+0x208/0x248
    [<ffffff80084de2c4>] driver_probe_device+0x98/0xc0
    [<ffffff80084dec54>] __device_attach_driver+0x9c/0xac
    [<ffffff80084dca74>] bus_for_each_drv+0x60/0x8c
    [<ffffff80084de634>] __device_attach+0x8c/0x100
    [<ffffff80084de6c8>] device_initial_probe+0x20/0x28
    [<ffffff80084dcbb8>] bus_probe_device+0x34/0x7c
    [<ffffff80084deb08>] deferred_probe_work_func+0x6c/0x98
    [<ffffff80080c3da8>] process_one_work+0x160/0x2f8

Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: default avatarAmit Kucheria <amit.kucheria@linaro.org>
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
parent 9d6b4b87
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -229,6 +229,8 @@ static int calibrate_8960(struct tsens_priv *priv)
	for (i = 0; i < num_read; i++, s++)
		s->offset = data[i];

	kfree(data);

	return 0;
}

+10 −2
Original line number Diff line number Diff line
@@ -145,8 +145,10 @@ static int calibrate_8916(struct tsens_priv *priv)
		return PTR_ERR(qfprom_cdata);

	qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
	if (IS_ERR(qfprom_csel))
	if (IS_ERR(qfprom_csel)) {
		kfree(qfprom_cdata);
		return PTR_ERR(qfprom_csel);
	}

	mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
	dev_dbg(priv->dev, "calibration mode is %d\n", mode);
@@ -181,6 +183,8 @@ static int calibrate_8916(struct tsens_priv *priv)
	}

	compute_intercept_slope(priv, p1, p2, mode);
	kfree(qfprom_cdata);
	kfree(qfprom_csel);

	return 0;
}
@@ -198,8 +202,10 @@ static int calibrate_8974(struct tsens_priv *priv)
		return PTR_ERR(calib);

	bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
	if (IS_ERR(bkp))
	if (IS_ERR(bkp)) {
		kfree(calib);
		return PTR_ERR(bkp);
	}

	calib_redun_sel =  bkp[1] & BKP_REDUN_SEL;
	calib_redun_sel >>= BKP_REDUN_SHIFT;
@@ -313,6 +319,8 @@ static int calibrate_8974(struct tsens_priv *priv)
	}

	compute_intercept_slope(priv, p1, p2, mode);
	kfree(calib);
	kfree(bkp);

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ static int calibrate_v1(struct tsens_priv *priv)
	}

	compute_intercept_slope(priv, p1, p2, mode);
	kfree(qfprom_cdata);

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

#include <linux/thermal.h>
#include <linux/regmap.h>
#include <linux/slab.h>

struct tsens_priv;