drivers: thermal: tsens: add timeout to get_tem_tsens_valid
Subsystems (3)
PATCH 2/3 drivers: thermal: tsens: add timeout to get_tem_tsens_valid
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.
--- drivers/thermal/qcom/tsens.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/thermal/qcom/tsens.c +16 -7
@@ -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; }
Signature · 1 line
2.30.2
PATCH 1/3 drivers: thermal: tsens: fix wrong check for tzd in irq handlers
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.
--- drivers/thermal/qcom/tsens.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/thermal/qcom/tsens.c +2 -2
@@ -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 ;
Signature · 1 line
2.30.2
PATCH 3/3 drivers: thermal: tsens: check if crit_int is supported in read_irq_state
In reply to Ansuel SmithFrom: Robert Marko <[email protected]>
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.
--- drivers/thermal/qcom/tsens.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
drivers/thermal/qcom/tsens.c +15 -9
@@ -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 ;
Signature · 1 line
2.30.2