summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/iio/industrialio-buffer.c46
-rw-r--r--include/linux/iio/buffer.h4
-rw-r--r--include/linux/iio/iio-opaque.h4
3 files changed, 54 insertions, 0 deletions
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index a95cc2da56be..4209e933ab80 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1732,6 +1732,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
*
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index b6928ac5c63d..451379a3984a 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -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);
diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
index c9504e9da571..2be12b7b5dc5 100644
--- a/include/linux/iio/iio-opaque.h
+++ b/include/linux/iio/iio-opaque.h
@@ -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
@@ -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;