[PATCH] iio: inv_sensors: prevent timestamps going back in time in transitions
From: Jean-Baptiste Maneyrol via B4 Relay
Date: Tue Oct 20 2026 - 11:27:17 EST
From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@xxxxxxx>
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@xxxxxxxxxxxxxxx
Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@xxxxxxx>
---
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 <jean-baptiste.maneyrol@xxxxxxx>