Re: [PATCH 3/4] iio: buffer: cache largest scan element size
From: Nuno Sá
Date: Mon Mar 02 2026 - 07:16:00 EST
On Sun, 2026-03-01 at 14:24 -0600, David Lechner wrote:
> Cache the largest scan element size of elements enabled in a scan
> buffer. This will be used later to ensure proper alignment of the
> timestamp element in the scan buffer.
>
> The new field could not be placed in struct iio_dev_opaque because we
> will need to access it in a static inline function later, so we make it
> __private instead. It is only intended to be used by core IIO code.
>
> Signed-off-by: David Lechner <dlechner@xxxxxxxxxxxx>
> ---
> drivers/iio/industrialio-buffer.c | 14 +++++++++++---
> include/linux/iio/iio.h | 3 +++
> 2 files changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index 71dfc81cb9e5..83e9392f949f 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -765,7 +765,8 @@ static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
>
> static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
> const unsigned long *mask, bool timestamp,
> - unsigned int *scan_bytes)
> + unsigned int *scan_bytes,
> + unsigned int *largest_element_size)
> {
> unsigned int bytes = 0;
> int length, i, largest = 0;
> @@ -793,6 +794,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
>
> *scan_bytes = ALIGN(bytes, largest);
>
> + if (largest_element_size)
> + *largest_element_size = largest;
I might be missing something but it seems we now have two paths:
1. Go with 32 bytes
2. Go with 24 bytes (natural alignment)
ABI was not clear so I'm not sure if we do want to enforce/treat repeated values as one single
element? If so, nothing to change. But if not, we could re-think the approach and save some bytes.
Marginal savings though so If having the smaller buffer is not straight enough I would be ok with
the simplicity tradeoff.
- Nuno Sá
> +
> return 0;
> }
>
> @@ -848,7 +852,7 @@ static int iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
> return 0;
>
> ret = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
> - buffer->scan_timestamp, &bytes);
> + buffer->scan_timestamp, &bytes, NULL);
> if (ret)
> return ret;
>
> @@ -892,6 +896,7 @@ struct iio_device_config {
> unsigned int watermark;
> const unsigned long *scan_mask;
> unsigned int scan_bytes;
> + unsigned int largest_scan_element_size;
> bool scan_timestamp;
> };
>
> @@ -997,7 +1002,8 @@ static int iio_verify_update(struct iio_dev *indio_dev,
> }
>
> ret = iio_compute_scan_bytes(indio_dev, scan_mask, scan_timestamp,
> - &config->scan_bytes);
> + &config->scan_bytes,
> + &config->largest_scan_element_size);
> if (ret)
> return ret;
>
> @@ -1155,6 +1161,8 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
> indio_dev->active_scan_mask = config->scan_mask;
> ACCESS_PRIVATE(indio_dev, scan_timestamp) = config->scan_timestamp;
> indio_dev->scan_bytes = config->scan_bytes;
> + ACCESS_PRIVATE(indio_dev, largest_scan_element_size) =
> + config->largest_scan_element_size;
> iio_dev_opaque->currentmode = config->mode;
>
> iio_update_demux(indio_dev);
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index a9ecff191bd9..85bcb5f8ae15 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -584,6 +584,8 @@ struct iio_buffer_setup_ops {
> * and owner
> * @buffer: [DRIVER] any buffer present
> * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux
> + * @largest_scan_element_size: [INTERN] cache of the largest scan element size
> + * among the channels selected in the scan mask
> * @available_scan_masks: [DRIVER] optional array of allowed bitmasks. Sort the
> * array in order of preference, the most preferred
> * masks first.
> @@ -610,6 +612,7 @@ struct iio_dev {
>
> struct iio_buffer *buffer;
> int scan_bytes;
> + unsigned int __private largest_scan_element_size;
>
> const unsigned long *available_scan_masks;
> unsigned int __private masklength;