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

Commit fc1c120d authored by Gopala Krishna Nuthaki's avatar Gopala Krishna Nuthaki
Browse files

drivers: thermal: Avoid multiple TSENS controller re-init simultaneously



If TSENS controller went to bad state while reading temperature of
a sensor, TSENS invokes controller re-init code for all controller
and then notifies the thermal framework to re-evaluate thermal for
each sensor. There is a possibility that while executing TSENS
re-init code, another sensor temperature read request can be
initiated and it could lead to another TSENS controller re-init
code execution.
Use an atomic variable to check above mentioned path and avoid
multiple TSENS re-init at same time.

Change-Id: Ied3c40356730fdf373be36b08f4af20b791afe8c
Signed-off-by: default avatarGopala Krishna Nuthaki <gnuthaki@codeaurora.org>
parent 0ea391ba
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ struct tsens_device {
	struct workqueue_struct		*tsens_reinit_work;
	struct work_struct		therm_fwk_notify;
	bool				tsens_reinit_wa;
	int                             tsens_reinit_cnt;
	struct tsens_sensor             sensor[0];
};

+30 −2
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@

#define TSENS_INIT_ID	0x5
#define TSENS_RECOVERY_LOOP_COUNT 5
#define TSENS_RE_INIT_MAX_COUNT   5

static void msm_tsens_convert_temp(int last_temp, int *temp)
{
@@ -87,6 +88,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
	void __iomem *sensor_addr, *trdy;
	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, count = 0;
	int tsens_ret;
	static atomic_t in_tsens_reinit;

	if (!sensor)
		return -EINVAL;
@@ -99,8 +101,14 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)

	if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >>
			TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) {
		if (atomic_read(&in_tsens_reinit)) {
			pr_err("%s: tsens re-init is in progress\n", __func__);
			return -EAGAIN;
		}

		pr_err("%s: tsens device first round not complete0x%x\n",
			__func__, code);

		/* Wait for 2.5 ms for tsens controller to recover */
		do {
			udelay(500);
@@ -117,10 +125,26 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
		 * proceed with SCM call to re-init it
		 */
		if (tmdev->tsens_reinit_wa) {
			if (atomic_read(&in_tsens_reinit)) {
				pr_err("%s: tsens re-init is in progress\n",
					__func__);
				return -EAGAIN;
			}

			atomic_set(&in_tsens_reinit, 1);

			if (tmdev->ops->dbg)
				tmdev->ops->dbg(tmdev, 0,
					TSENS_DBG_LOG_BUS_ID_DATA, NULL);

			if (tmdev->tsens_reinit_cnt >=
					TSENS_RE_INIT_MAX_COUNT) {
				pr_err(
				"%s: TSENS not recovered after %d re-init\n",
					__func__, tmdev->tsens_reinit_cnt);
				BUG();
			}

			/*Make an scm call to re-init TSENS */
			TSENS_DBG(tmdev, "%s",
					"Calling TZ to re-init TSENS\n");
@@ -137,6 +161,9 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
					__func__, tsens_ret);
				BUG();
			}
			tmdev->tsens_reinit_cnt++;
			atomic_set(&in_tsens_reinit, 0);

			/* Notify thermal fwk */
			list_for_each_entry(tmdev_itr,
						&tsens_device_list, list) {
@@ -154,6 +181,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
sensor_read:

	tmdev->trdy_fail_ctr = 0;
	tmdev->tsens_reinit_cnt = 0;

	code = readl_relaxed_no_log(sensor_addr +
			(sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));