linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/3] drivers: thermal: tsens: add timeout to get_tem_tsens_valid
@ 2021-05-18 23:43 Ansuel Smith
  2021-05-18 23:43 ` [PATCH 3/3] drivers: thermal: tsens: check if crit_int is supported in read_irq_state Ansuel Smith
  2021-05-18 23:43 ` [PATCH 1/3] drivers: thermal: tsens: fix wrong check for tzd in irq handlers Ansuel Smith
  0 siblings, 2 replies; 3+ messages in thread
From: Ansuel Smith @ 2021-05-18 23:43 UTC (permalink / raw)
  To: Thara Gopinath
  Cc: Ansuel Smith, Andy Gross, Bjorn Andersson, Amit Kucheria,
	Zhang Rui, Daniel Lezcano, linux-arm-msm, linux-pm, linux-kernel

The function can loop and lock the system if for whatever reason the bit
for the target sensor is NEVER valid. This is the case if a sensor is
disabled by the factory and the valid bit is never reported as actually
valid. Add a timeout check and exit if a timeout occurs. As this is
a very rare condition, handle the timeout only if the first read fails.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
 drivers/thermal/qcom/tsens.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index b1162e566a70..38afde1a599f 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -599,6 +599,7 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp)
 	int hw_id = s->hw_id;
 	u32 temp_idx = LAST_TEMP_0 + hw_id;
 	u32 valid_idx = VALID_0 + hw_id;
+	unsigned long timeout;
 	u32 valid;
 	int ret;
 
@@ -607,13 +608,21 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp)
 		ret = regmap_field_read(priv->rf[valid_idx], &valid);
 		if (ret)
 			return ret;
-		while (!valid) {
-			/* Valid bit is 0 for 6 AHB clock cycles.
-			 * At 19.2MHz, 1 AHB clock is ~60ns.
-			 * We should enter this loop very, very rarely.
-			 */
-			ndelay(400);
-			ret = regmap_field_read(priv->rf[valid_idx], &valid);
+
+		if (!valid) {
+			timeout = jiffies + msecs_to_jiffies(20);
+
+			do {
+				/* Valid bit is 0 for 6 AHB clock cycles.
+				 * At 19.2MHz, 1 AHB clock is ~60ns.
+				 * We should enter this loop very, very rarely.
+				 */
+				ndelay(400);
+				ret = regmap_field_read(priv->rf[valid_idx], &valid);
+				if (valid || ret)
+					break;
+			} while (!(ret = time_after_eq(jiffies, timeout)));
+
 			if (ret)
 				return ret;
 		}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 3/3] drivers: thermal: tsens: check if crit_int is supported in read_irq_state
  2021-05-18 23:43 [PATCH 2/3] drivers: thermal: tsens: add timeout to get_tem_tsens_valid Ansuel Smith
@ 2021-05-18 23:43 ` Ansuel Smith
  2021-05-18 23:43 ` [PATCH 1/3] drivers: thermal: tsens: fix wrong check for tzd in irq handlers Ansuel Smith
  1 sibling, 0 replies; 3+ messages in thread
From: Ansuel Smith @ 2021-05-18 23:43 UTC (permalink / raw)
  To: Thara Gopinath
  Cc: Robert Marko, Ansuel Smith, Andy Gross, Bjorn Andersson,
	Amit Kucheria, Zhang Rui, Daniel Lezcano, linux-arm-msm,
	linux-pm, linux-kernel

From: Robert Marko <robimarko@gmail.com>

Check if crit_int is supported by the current tsens feat and read crit
field only if needed or the kernel panic for reading unreadable memory.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
 drivers/thermal/qcom/tsens.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 38afde1a599f..27777a05f755 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -325,16 +325,22 @@ static int tsens_read_irq_state(struct tsens_priv *priv, u32 hw_id,
 		ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask);
 		if (ret)
 			return ret;
-		ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id],
-					&d->crit_irq_clear);
-		if (ret)
-			return ret;
-		ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id],
-					&d->crit_irq_mask);
-		if (ret)
-			return ret;
+		if (priv->feat->crit_int) {
+			ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id],
+						&d->crit_irq_clear);
+			if (ret)
+				return ret;
+			ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id],
+						&d->crit_irq_mask);
+			if (ret)
+				return ret;
 
-		d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id);
+			d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id);
+		} else {
+			d->crit_irq_clear = 0;
+			d->crit_irq_mask = 0;
+			d->crit_thresh = 0;
+		}
 	} else {
 		/* No mask register on older TSENS */
 		d->up_irq_mask = 0;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 1/3] drivers: thermal: tsens: fix wrong check for tzd in irq handlers
  2021-05-18 23:43 [PATCH 2/3] drivers: thermal: tsens: add timeout to get_tem_tsens_valid Ansuel Smith
  2021-05-18 23:43 ` [PATCH 3/3] drivers: thermal: tsens: check if crit_int is supported in read_irq_state Ansuel Smith
@ 2021-05-18 23:43 ` Ansuel Smith
  1 sibling, 0 replies; 3+ messages in thread
From: Ansuel Smith @ 2021-05-18 23:43 UTC (permalink / raw)
  To: Thara Gopinath
  Cc: Ansuel Smith, Amit Kucheria, Andy Gross, Bjorn Andersson,
	Zhang Rui, Daniel Lezcano, linux-pm, linux-arm-msm, linux-kernel

Some device can have some thermal sensor disabled from the factory. The
current 2 irq handler functions check all the sensor by default and the
check if the sensor was actually registered is wrong. The tzd is
actually never set if the registration fail hence the IS_ERR check is
wrong.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
 drivers/thermal/qcom/tsens.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 4c7ebd1d3f9c..b1162e566a70 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -417,7 +417,7 @@ static irqreturn_t tsens_critical_irq_thread(int irq, void *data)
 		const struct tsens_sensor *s = &priv->sensor[i];
 		u32 hw_id = s->hw_id;
 
-		if (IS_ERR(s->tzd))
+		if (!s->tzd)
 			continue;
 		if (!tsens_threshold_violated(priv, hw_id, &d))
 			continue;
@@ -467,7 +467,7 @@ static irqreturn_t tsens_irq_thread(int irq, void *data)
 		const struct tsens_sensor *s = &priv->sensor[i];
 		u32 hw_id = s->hw_id;
 
-		if (IS_ERR(s->tzd))
+		if (!s->tzd)
 			continue;
 		if (!tsens_threshold_violated(priv, hw_id, &d))
 			continue;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-05-18 23:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-18 23:43 [PATCH 2/3] drivers: thermal: tsens: add timeout to get_tem_tsens_valid Ansuel Smith
2021-05-18 23:43 ` [PATCH 3/3] drivers: thermal: tsens: check if crit_int is supported in read_irq_state Ansuel Smith
2021-05-18 23:43 ` [PATCH 1/3] drivers: thermal: tsens: fix wrong check for tzd in irq handlers Ansuel Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).