Skip to content

Commit

Permalink
iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
Browse files Browse the repository at this point in the history
Whilst it is almost always possible to arrange for scan data to be
read directly into a buffer that is suitable for passing to
iio_push_to_buffers_with_timestamp(), there are a few places where
leading data needs to be skipped over.

For these cases introduce a function that will allocate an appropriate
sized and aligned bounce buffer (if not already allocated) and copy
the unaligned data into that before calling
iio_push_to_buffers_with_timestamp() on the bounce buffer.
We tie the lifespace of this buffer to that of the iio_dev.dev
which should ensure no memory leaks occur.

Signed-off-by: Jonathan Cameron <[email protected]>
Reviewed-by: Nuno Sá <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
jic23 committed Oct 19, 2021
1 parent b18831c commit 95ec3fd
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
46 changes: 46 additions & 0 deletions drivers/iio/industrialio-buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,52 @@ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
}
EXPORT_SYMBOL_GPL(iio_push_to_buffers);

/**
* iio_push_to_buffers_with_ts_unaligned() - push to registered buffer,
* no alignment or space requirements.
* @indio_dev: iio_dev structure for device.
* @data: channel data excluding the timestamp.
* @data_sz: size of data.
* @timestamp: timestamp for the sample data.
*
* This special variant of iio_push_to_buffers_with_timestamp() does
* not require space for the timestamp, or 8 byte alignment of data.
* It does however require an allocation on first call and additional
* copies on all calls, so should be avoided if possible.
*/
int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev,
const void *data,
size_t data_sz,
int64_t timestamp)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);

/*
* Conservative estimate - we can always safely copy the minimum
* of either the data provided or the length of the destination buffer.
* This relaxed limit allows the calling drivers to be lax about
* tracking the size of the data they are pushing, at the cost of
* unnecessary copying of padding.
*/
data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz);
if (iio_dev_opaque->bounce_buffer_size != indio_dev->scan_bytes) {
void *bb;

bb = devm_krealloc(&indio_dev->dev,
iio_dev_opaque->bounce_buffer,
indio_dev->scan_bytes, GFP_KERNEL);
if (!bb)
return -ENOMEM;
iio_dev_opaque->bounce_buffer = bb;
iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes;
}
memcpy(iio_dev_opaque->bounce_buffer, data, data_sz);
return iio_push_to_buffers_with_timestamp(indio_dev,
iio_dev_opaque->bounce_buffer,
timestamp);
}
EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned);

/**
* iio_buffer_release() - Free a buffer's resources
* @ref: Pointer to the kref embedded in the iio_buffer struct
Expand Down
4 changes: 4 additions & 0 deletions include/linux/iio/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
return iio_push_to_buffers(indio_dev, data);
}

int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev,
const void *data, size_t data_sz,
int64_t timestamp);

bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
const unsigned long *mask);

Expand Down
4 changes: 4 additions & 0 deletions include/linux/iio/iio-opaque.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* @groupcounter: index of next attribute group
* @legacy_scan_el_group: attribute group for legacy scan elements attribute group
* @legacy_buffer_group: attribute group for legacy buffer attributes group
* @bounce_buffer: for devices that call iio_push_to_buffers_with_timestamp_unaligned()
* @bounce_buffer_size: size of currently allocate bounce buffer
* @scan_index_timestamp: cache of the index to the timestamp
* @clock_id: timestamping clock posix identifier
* @chrdev: associated character device
Expand Down Expand Up @@ -50,6 +52,8 @@ struct iio_dev_opaque {
int groupcounter;
struct attribute_group legacy_scan_el_group;
struct attribute_group legacy_buffer_group;
void *bounce_buffer;
size_t bounce_buffer_size;

unsigned int scan_index_timestamp;
clockid_t clock_id;
Expand Down

0 comments on commit 95ec3fd

Please sign in to comment.