Commit 40c48fb7 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Jonathan Cameron

iio: common: st_sensors: fix possible infinite loop in st_sensors_irq_thread

Return a boolean value in st_sensors_new_samples_available routine in
order to avoid an infinite loop in st_sensors_irq_thread if
stat_drdy.addr is not defined or stat_drdy read fails

Fixes: 90efe055 ("iio: st_sensors: harden interrupt handling")
Reported-by: default avatarJonathan Cameron <jic23@kernel.org>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/c9ec69ed349e7200c779fd7a5bf04c1aaa2817aa.1607438132.git.lorenzo@kernel.org
Cc: <Stable@vger.kernel.org>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent efd597b2
...@@ -23,35 +23,31 @@ ...@@ -23,35 +23,31 @@
* @sdata: Sensor data. * @sdata: Sensor data.
* *
* returns: * returns:
* 0 - no new samples available * false - no new samples available or read error
* 1 - new samples available * true - new samples available
* negative - error or unknown
*/ */
static int st_sensors_new_samples_available(struct iio_dev *indio_dev, static bool st_sensors_new_samples_available(struct iio_dev *indio_dev,
struct st_sensor_data *sdata) struct st_sensor_data *sdata)
{ {
int ret, status; int ret, status;
/* How would I know if I can't check it? */ /* How would I know if I can't check it? */
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
return -EINVAL; return true;
/* No scan mask, no interrupt */ /* No scan mask, no interrupt */
if (!indio_dev->active_scan_mask) if (!indio_dev->active_scan_mask)
return 0; return false;
ret = regmap_read(sdata->regmap, ret = regmap_read(sdata->regmap,
sdata->sensor_settings->drdy_irq.stat_drdy.addr, sdata->sensor_settings->drdy_irq.stat_drdy.addr,
&status); &status);
if (ret < 0) { if (ret < 0) {
dev_err(sdata->dev, "error checking samples available\n"); dev_err(sdata->dev, "error checking samples available\n");
return ret; return false;
} }
if (status & sdata->sensor_settings->drdy_irq.stat_drdy.mask) return !!(status & sdata->sensor_settings->drdy_irq.stat_drdy.mask);
return 1;
return 0;
} }
/** /**
...@@ -180,9 +176,15 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -180,9 +176,15 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
/* Tell the interrupt handler that we're dealing with edges */ /* Tell the interrupt handler that we're dealing with edges */
if (irq_trig == IRQF_TRIGGER_FALLING || if (irq_trig == IRQF_TRIGGER_FALLING ||
irq_trig == IRQF_TRIGGER_RISING) irq_trig == IRQF_TRIGGER_RISING) {
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) {
dev_err(&indio_dev->dev,
"edge IRQ not supported w/o stat register.\n");
err = -EOPNOTSUPP;
goto iio_trigger_free;
}
sdata->edge_irq = true; sdata->edge_irq = true;
else } else {
/* /*
* If we're not using edges (i.e. level interrupts) we * If we're not using edges (i.e. level interrupts) we
* just mask off the IRQ, handle one interrupt, then * just mask off the IRQ, handle one interrupt, then
...@@ -190,6 +192,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -190,6 +192,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
* interrupt handler top half again and start over. * interrupt handler top half again and start over.
*/ */
irq_trig |= IRQF_ONESHOT; irq_trig |= IRQF_ONESHOT;
}
/* /*
* If the interrupt pin is Open Drain, by definition this * If the interrupt pin is Open Drain, by definition this
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment