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:
Родитель
efd597b283
Коммит
40c48fb79b
|
@ -23,35 +23,31 @@
|
|||
* @sdata: Sensor data.
|
||||
*
|
||||
* returns:
|
||||
* 0 - no new samples available
|
||||
* 1 - new samples available
|
||||
* negative - error or unknown
|
||||
* false - no new samples available or read error
|
||||
* true - new samples available
|
||||
*/
|
||||
static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
||||
struct st_sensor_data *sdata)
|
||||
static bool st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
||||
struct st_sensor_data *sdata)
|
||||
{
|
||||
int ret, status;
|
||||
|
||||
/* How would I know if I can't check it? */
|
||||
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
|
||||
return -EINVAL;
|
||||
return true;
|
||||
|
||||
/* No scan mask, no interrupt */
|
||||
if (!indio_dev->active_scan_mask)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
ret = regmap_read(sdata->regmap,
|
||||
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
|
||||
&status);
|
||||
if (ret < 0) {
|
||||
dev_err(sdata->dev, "error checking samples available\n");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status & sdata->sensor_settings->drdy_irq.stat_drdy.mask)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return !!(status & sdata->sensor_settings->drdy_irq.stat_drdy.mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,9 +176,15 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
|||
|
||||
/* Tell the interrupt handler that we're dealing with edges */
|
||||
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;
|
||||
else
|
||||
} else {
|
||||
/*
|
||||
* If we're not using edges (i.e. level interrupts) we
|
||||
* 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.
|
||||
*/
|
||||
irq_trig |= IRQF_ONESHOT;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the interrupt pin is Open Drain, by definition this
|
||||
|
|
Загрузка…
Ссылка в новой задаче