aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c')
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index e2737dc71b67..0a2c2eace3a2 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -395,13 +395,29 @@ static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
{
struct st_lsm6dsx_hw *hw = private;
- int count;
+ int fifo_len = 0, len;
- mutex_lock(&hw->fifo_lock);
- count = st_lsm6dsx_read_fifo(hw);
- mutex_unlock(&hw->fifo_lock);
+ /*
+ * If we are using edge IRQs, new samples can arrive while
+ * processing current interrupt since there are no hw
+ * guarantees the irq line stays "low" long enough to properly
+ * detect the new interrupt. In this case the new sample will
+ * be missed.
+ * Polling FIFO status register allow us to read new
+ * samples even if the interrupt arrives while processing
+ * previous data and the timeslot where the line is "low" is
+ * too short to be properly detected.
+ */
+ do {
+ mutex_lock(&hw->fifo_lock);
+ len = st_lsm6dsx_read_fifo(hw);
+ mutex_unlock(&hw->fifo_lock);
+
+ if (len > 0)
+ fifo_len += len;
+ } while (len > 0);
- return !count ? IRQ_NONE : IRQ_HANDLED;
+ return fifo_len ? IRQ_HANDLED : IRQ_NONE;
}
static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)