]> www.infradead.org Git - linux.git/commitdiff
iio: imu: inv_icm42600: stabilized timestamp in interrupt
authorJean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Wed, 29 May 2024 15:47:17 +0000 (15:47 +0000)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sun, 2 Jun 2024 10:56:40 +0000 (11:56 +0100)
Use IRQF_ONESHOT flag to ensure the timestamp is not updated in the
hard handler during the thread handler. And compute and use the
effective watermark value that correspond to this first timestamp.

This way we can ensure the timestamp is always corresponding to the
value used by the timestamping mechanism. Otherwise, it is possible
that between FIFO count read and FIFO processing the timestamp is
overwritten in the hard handler.

Fixes: ec74ae9fd37c ("iio: imu: inv_icm42600: add accurate timestamping")
Cc: stable@vger.kernel.org
Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Link: https://lore.kernel.org/r/20240529154717.651863-1-inv.git-commit@tdk.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

index 63b85ec88c131f7558bb143fb04f13428cd57081..a8cf74c84c3c4560e80e2b87f68d55fe1860ba01 100644 (file)
@@ -222,10 +222,15 @@ int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st)
        latency_accel = period_accel * wm_accel;
 
        /* 0 value for watermark means that the sensor is turned off */
+       if (wm_gyro == 0 && wm_accel == 0)
+               return 0;
+
        if (latency_gyro == 0) {
                watermark = wm_accel;
+               st->fifo.watermark.eff_accel = wm_accel;
        } else if (latency_accel == 0) {
                watermark = wm_gyro;
+               st->fifo.watermark.eff_gyro = wm_gyro;
        } else {
                /* compute the smallest latency that is a multiple of both */
                if (latency_gyro <= latency_accel)
@@ -241,6 +246,13 @@ int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st)
                watermark = latency / period;
                if (watermark < 1)
                        watermark = 1;
+               /* update effective watermark */
+               st->fifo.watermark.eff_gyro = latency / period_gyro;
+               if (st->fifo.watermark.eff_gyro < 1)
+                       st->fifo.watermark.eff_gyro = 1;
+               st->fifo.watermark.eff_accel = latency / period_accel;
+               if (st->fifo.watermark.eff_accel < 1)
+                       st->fifo.watermark.eff_accel = 1;
        }
 
        /* compute watermark value in bytes */
@@ -514,7 +526,7 @@ int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
        /* handle gyroscope timestamp and FIFO data parsing */
        if (st->fifo.nb.gyro > 0) {
                ts = &gyro_st->ts;
-               inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro,
+               inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_gyro,
                                                st->timestamp.gyro);
                ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
                if (ret)
@@ -524,7 +536,7 @@ int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
        /* handle accelerometer timestamp and FIFO data parsing */
        if (st->fifo.nb.accel > 0) {
                ts = &accel_st->ts;
-               inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel,
+               inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_accel,
                                                st->timestamp.accel);
                ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
                if (ret)
@@ -577,6 +589,9 @@ int inv_icm42600_buffer_init(struct inv_icm42600_state *st)
        unsigned int val;
        int ret;
 
+       st->fifo.watermark.eff_gyro = 1;
+       st->fifo.watermark.eff_accel = 1;
+
        /*
         * Default FIFO configuration (bits 7 to 5)
         * - use invalid value
index 8b85ee333bf8f6ba7bec27757b784ee792a35214..f6c85daf42b00bfb7b1ccabd59195819088e3dc7 100644 (file)
@@ -32,6 +32,8 @@ struct inv_icm42600_fifo {
        struct {
                unsigned int gyro;
                unsigned int accel;
+               unsigned int eff_gyro;
+               unsigned int eff_accel;
        } watermark;
        size_t count;
        struct {
index 96116a68ab291bc541f8b84c5853662cc9a3cf50..62fdae530334af744039f865200fb635f3be36a9 100644 (file)
@@ -537,6 +537,7 @@ static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
        if (ret)
                return ret;
 
+       irq_type |= IRQF_ONESHOT;
        return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp,
                                         inv_icm42600_irq_handler, irq_type,
                                         "inv_icm42600", st);