From: Jean-Baptiste Maneyrol Ensure when computing first timestamp and when applying odr change, that the next timestamp will not be lower than the previous one. This way there is no risk to have a timestamp going back in time, meaning being lower than the previous one. It already can never happen without a transition because we are generating timestamps by adding the period to the last timestamp. Fixes: 0ecc363ccea7 ("iio: make invensense timestamp module generic") Cc: stable@vger.kernel.org Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 16 ++++++++++++---- include/linux/iio/common/inv_sensors_timestamp.h | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c index 8c9e81a77e68..9040da80f0c7 100644 --- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c @@ -133,10 +133,15 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, return; /* no previous data, compute theoretical value from interrupt */ - if (ts->timestamp == 0) { + if (!ts->init) { /* elapsed time: sensor period * sensor samples number */ interval = (s64)ts->period * (s64)sample_nb; - ts->timestamp = timestamp - interval; + delta = timestamp - interval; + /* prevent next timestamp to be lower than the last one */ + if ((delta + ts->period) > ts->timestamp) + ts->timestamp = delta; + ts->init = true; + } /* update delta timestamps and estimated period */ @@ -184,7 +189,7 @@ void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts, u32 fifo_period, size_t fifo_nb, unsigned int fifo_no) { - s64 interval; + s64 interval, timestamp; u32 fifo_mult; if (ts->new_mult == 0) @@ -207,7 +212,10 @@ void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts, fifo_period = fifo_mult * ts->chip_period.val; /* computes time interval between interrupt and this sample */ interval = (s64)(fifo_nb - fifo_no) * (s64)fifo_period; - ts->timestamp = ts->it.up - interval; + timestamp = ts->it.up - interval; + /* prevent next timestamp to be lower than current one */ + if ((timestamp + ts->period) > ts->timestamp) + ts->timestamp = timestamp; } } EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_apply_odr, "IIO_INV_SENSORS_TIMESTAMP"); diff --git a/include/linux/iio/common/inv_sensors_timestamp.h b/include/linux/iio/common/inv_sensors_timestamp.h index 4f08204ede3b..91690778ae88 100644 --- a/include/linux/iio/common/inv_sensors_timestamp.h +++ b/include/linux/iio/common/inv_sensors_timestamp.h @@ -66,6 +66,7 @@ struct inv_sensors_timestamp { u32 new_mult; u32 period; struct inv_sensors_timestamp_acc chip_period; + bool init; }; void inv_sensors_timestamp_init(struct inv_sensors_timestamp *ts, @@ -94,7 +95,7 @@ static inline void inv_sensors_timestamp_reset(struct inv_sensors_timestamp *ts) ts->it = interval_init; ts->delta = interval_init; ts->delta_counter = 0; - ts->timestamp = 0; + ts->init = false; } #endif --- base-commit: 43ffda3c7f8456bbe641ae8249a077a361b97880 change-id: 20261020-iio-common-inv-sensors-fixes-for-preventing-timestamp-in-past-8da19f683084 Best regards, -- Jean-Baptiste Maneyrol