]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iio: buffer: fix timestamp alignment when quaternion in scan
authorDavid Lechner <dlechner@baylibre.com>
Sun, 8 Mar 2026 01:44:13 +0000 (19:44 -0600)
committerJonathan Cameron <jic23@kernel.org>
Mon, 27 Apr 2026 08:58:15 +0000 (09:58 +0100)
Fix timestamp alignment when a scan buffer contains an element larger
than sizeof(int64_t). Currently s32 quaternions are the only such
element, and the one driver that has this (hid-sensor-rotation) has a
workaround in place already so this change does not affect it.

Previously, we assumed that the timestamp would always be 8-byte aligned
relative to the end of the scan buffer, but in the case of a scan buffer
a 16-byte quaternion vector, scan_bytes == 32, but the timestamp needs
to be placed at offset 16, not 24.

ts_offset is now a value in bytes so we have to change how the array
access is done.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
include/linux/iio/buffer.h

index d37f82678f716dabfd4eb3b87cd7bb00f146046d..8fd0d57d238fc9aacffc9f43866376ec6d2bca31 100644 (file)
@@ -34,8 +34,16 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
        void *data, int64_t timestamp)
 {
        if (ACCESS_PRIVATE(indio_dev, scan_timestamp)) {
-               size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1;
-               ((int64_t *)data)[ts_offset] = timestamp;
+               size_t ts_offset = ACCESS_PRIVATE(indio_dev, scan_timestamp_offset);
+
+               /*
+                * The size of indio_dev->scan_bytes is always aligned to the
+                * largest scan element's alignment (see iio_compute_scan_bytes()).
+                * So there may be padding after the timestamp. ts_offset contains
+                * the offset in bytes that was already computed for correctly
+                * aligning the timestamp.
+                */
+               *(int64_t *)(data + ts_offset) = timestamp;
        }
 
        return iio_push_to_buffers(indio_dev, data);