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

Commit cf081bf2 authored by Manaf Meethalavalappu Pallikunhi's avatar Manaf Meethalavalappu Pallikunhi
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: I3321e490f0276ba4b58a778177d234abb867699b
Signed-off-by: default avatarManaf Meethalavalappu Pallikunhi <manafm@codeaurora.org>
parent 4266f5b9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef __QCOM_TSENS_H__
@@ -214,6 +214,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 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
@@ -69,6 +69,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)
{
@@ -88,6 +89,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
	unsigned int code, ret, tsens_ret;
	void __iomem *sensor_addr, *trdy;
	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, count = 0;
	static atomic_t in_tsens_reinit;

	if (!sensor)
		return -EINVAL;
@@ -100,8 +102,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);
@@ -120,9 +128,26 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
		if (tmdev->tsens_reinit_wa) {
			struct scm_desc desc = { 0 };

			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");
@@ -141,6 +166,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) {
@@ -158,6 +186,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));