diff mbox series

[v3,06/20] iio: dummy: Use a fixed structure to build up scan to push to buffers.

Message ID 20250413103443.2420727-7-jic23@kernel.org (mailing list archive)
State Accepted
Headers show
Series IIO: Introduce iio_push_to_buffers_with_ts() taking an input buffer length argument. | expand

Commit Message

Jonathan Cameron April 13, 2025, 10:34 a.m. UTC
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

It has long been discouraged for drivers to make use of iio_dev->scan_bytes
directly as that is an implementation detail of the core. As such our
example driver should definitely not be doing so.

In order to illustrate the more complex case, where a DMA safe buffer is
needed, continue to kzalloc() the storage (but with a structure definition
to provide an explicit data layout). Also add comments on when a DMA safe
buffer is necessary and the two common ways of obtaining one.

Whilst we have a mixture of signed and unsigned channels, the unsigned
channels have ranges that can be stored in a signed value - hence
use signed storage for all channels, simplifying the structure definition.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
v3: Go back to kzalloc but with a structure definition. (Andy)
v2: Add a comment about stack buffers not being DMA safe.
---
 drivers/iio/dummy/iio_simple_dummy_buffer.c | 25 +++++++++++++++------
 1 file changed, 18 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
index 288880346707..d0a7343e1b35 100644
--- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
+++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
@@ -31,6 +31,11 @@  static const s16 fakedata[] = {
 	[DUMMY_INDEX_ACCELX] = 344,
 };
 
+struct dummy_scan {
+	s16 data[ARRAY_SIZE(fakedata)];
+	aligned_s64 timestamp;
+};
+
 /**
  * iio_simple_dummy_trigger_h() - the trigger handler function
  * @irq: the interrupt number
@@ -45,11 +50,18 @@  static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
+	struct dummy_scan *scan;
 	int i = 0, j;
-	u16 *data;
 
-	data = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (!data)
+	/*
+	 * Note that some buses such as SPI require DMA safe buffers which
+	 * cannot be on the stack. Two easy ways to do this:
+	 *  - Local kzalloc (as done here)
+	 *  - A buffer at the end of the structure accessed via iio_priv()
+	 *    that is marked __aligned(IIO_DMA_MINALIGN).
+	 */
+	scan = kzalloc(sizeof(*scan), GFP_KERNEL);
+	if (!scan)
 		goto done;
 
 	/*
@@ -69,13 +81,12 @@  static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 	 * constant table fakedata.
 	 */
 	iio_for_each_active_channel(indio_dev, j)
-		data[i++] = fakedata[j];
+		scan->data[i++] = fakedata[j];
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, scan,
 					   iio_get_time_ns(indio_dev));
 
-	kfree(data);
-
+	kfree(scan);
 done:
 	/*
 	 * Tell the core we are done with this trigger and ready for the