From fc1c120db7852374dd5845fcca687a5196cfe01c Mon Sep 17 00:00:00 2001 From: Gopala Krishna Nuthaki Date: Fri, 26 Jun 2020 16:19:32 +0530 Subject: [PATCH] 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: Gopala Krishna Nuthaki --- drivers/thermal/tsens.h | 1 + drivers/thermal/tsens2xxx.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h index 24ccced348d7..6a264802a36e 100644 --- a/drivers/thermal/tsens.h +++ b/drivers/thermal/tsens.h @@ -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]; }; diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c index 576db65a9fd3..502b428a0917 100644 --- a/drivers/thermal/tsens2xxx.c +++ b/drivers/thermal/tsens2xxx.c @@ -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,16 +125,32 @@ 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"); + "Calling TZ to re-init TSENS\n"); ret = qcom_scm_tsens_reinit(&tsens_ret); TSENS_DBG(tmdev, "%s", - "return from scm call\n"); + "return from scm call\n"); if (ret) { pr_err("%s: scm call failed %d\n", __func__, ret); @@ -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));