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: 90efe05562
("iio: st_sensors: harden interrupt handling")
Reported-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Linus 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: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
efd597b283
commit
40c48fb79b
@ -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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
* 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
|
||||||
|
Loading…
Reference in New Issue
Block a user