All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases.
@ 2021-06-13 15:10 Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned() Jonathan Cameron
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-13 15:10 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

Thanks to Andy and Nuno for reviews.

Chances since V1/RFC:
* Renamed the function to iio_push_to_buffer_with_ts_unaligned()
* Fixed the various bugs people pointed out.
* Used more standard realloc handling to be more 'obviously' correct.
* Added some additional comments on the sizing of the copy to explain why
  it is a conservative estimate and may copy more than strictly necessary.

A few things we discussed I didn't do (for now)...

I decided against adding explicit bounce buffer allocation calls for now,
though I'm open to doing that in future if we find doing the somewhat hidden
realloc to be a problem.

I haven't computed a more precise data_sz as I don't thing the benefits
of a more precise copy or not passing the size, make it worth the slight
reduction in complexity for the callers.  Again, open to revisiting this
in future!

I tested it by hacking the dummy driver to shift it's data by one
byte and call iio_push_to_buffers_with_ts_unaligned().

Strictly a hack. I definitely don't want to move this driver over to this
new interface as it might encourage inappropriate use.

diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
index 59aa60d4ca37..b47af7df8efc 100644
--- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
+++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
@@ -19,6 +19,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <asm/unaligned.h>
 
 #include "iio_simple_dummy.h"
 
@@ -78,12 +79,13 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
                        j = find_next_bit(indio_dev->active_scan_mask,
                                          indio_dev->masklength, j);
                        /* random access read from the 'device' */
-                       data[i] = fakedata[j];
+//                     data[i] = fakedata[j];
+                       put_unaligned_le16(fakedata[j], ((u8 *)(&data[i])) + 1);
                        len += 2;
                }
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, data,
+       iio_push_to_buffers_with_ts_unaligned(indio_dev, ((u8 *)(data)) + 1, indio_dev->scan_bytes - 8,
                                           iio_get_time_ns(indio_dev));


v1 description:

I finally got around to do a manual audit of all the calls to
iio_push_to_buffers_with_timestamp() which has the somewhat odd requirements
of:
1. 8 byte alignment of the provided buffer.
2. space for an 8 byte naturally aligned timestamp to be inserted at the
   end.

Unfortunately there were rather a lot of these left, but time to bite the bullet
and clean them up.

As discussed previous in
https://lore.kernel.org/linux-iio/20200920112742.170751-1-jic23@kernel.org/
it is not easy to fix the alignment issue without requiring a bounce buffer.
This final part of the 4 sets of fixes is concerned with the cases where
bounce buffers are the proposed solutions.

In these cases we have hardware that reads a prefix that we wish to
drop. That makes it hard to directly read the data into the correct location.

Rather than implementing bouce buffers in each case, this set provides some
magic in the core to handle them via a new function.
iio_push_to_buffers_with_ts_na() - non aligned

Note this is totally untested as I don't have suitable hardware or emulation.
I can fake something up in the dummy driver or via QEMU but I definitely want
both eyes and testing on this series!

Jonathan Cameron (4):
  iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
  iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio
    buffers.
  iio: gyro: mpu3050: Fix alignment and size issues with buffers.
  iio: imu: adis16400: Fix buffer alignment requirements.

 drivers/iio/adc/ti-adc108s102.c   | 11 ++++----
 drivers/iio/gyro/mpu3050-core.c   | 24 ++++++++--------
 drivers/iio/imu/adis16400.c       | 20 ++++++++++----
 drivers/iio/industrialio-buffer.c | 46 +++++++++++++++++++++++++++++++
 include/linux/iio/buffer.h        |  4 +++
 include/linux/iio/iio-opaque.h    |  4 +++
 6 files changed, 86 insertions(+), 23 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
  2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
@ 2021-06-13 15:10 ` Jonathan Cameron
  2021-06-14  8:33   ` Sa, Nuno
  2021-06-13 15:10 ` [PATCH v2 2/4] iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio buffers Jonathan Cameron
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-13 15:10 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

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 <Jonathan.Cameron@huawei.com>
---
 drivers/iio/industrialio-buffer.c | 46 +++++++++++++++++++++++++++++++
 include/linux/iio/buffer.h        |  4 +++
 include/linux/iio/iio-opaque.h    |  4 +++
 3 files changed, 54 insertions(+)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index fdd623407b96..5241b5a5c6c0 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1730,6 +1730,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;
-- 
2.32.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/4] iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio buffers.
  2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned() Jonathan Cameron
@ 2021-06-13 15:10 ` Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 3/4] iio: gyro: mpu3050: Fix alignment and size issues with buffers Jonathan Cameron
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-13 15:10 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

Use the newly introduce iio_push_to_buffers_with_ts_unaligned() function
to ensure a bounce buffer is used to provide the required alignment and
space padding needed by the IIO core which requires the timestamp
is naturally aligned.  There will be a performance cost to this change
but it will ensure the driver works on platforms that do not support
unaligned 8 byte assignments, and with consumer drivers that may
assume natural alignment of the timestamp.

Issue found as part of an audit of all calls to
iio_push_to_buffers_with_timestamp()

Fixes: 7e87d11c9bda ("iio: adc: Add support for TI ADC108S102 and ADC128S102")
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
---
 drivers/iio/adc/ti-adc108s102.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c
index db902aef2abe..c8e48881c37f 100644
--- a/drivers/iio/adc/ti-adc108s102.c
+++ b/drivers/iio/adc/ti-adc108s102.c
@@ -75,9 +75,9 @@ struct adc108s102_state {
 	 *  rx_buf: |XX|R0|R1|R2|R3|R4|R5|R6|R7|tt|tt|tt|tt|
 	 *
 	 *  tx_buf: 8 channel read commands, plus 1 dummy command
-	 *  rx_buf: 1 dummy response, 8 channel responses, plus 64-bit timestamp
+	 *  rx_buf: 1 dummy response, 8 channel responses
 	 */
-	__be16				rx_buf[13] ____cacheline_aligned;
+	__be16				rx_buf[9] ____cacheline_aligned;
 	__be16				tx_buf[9] ____cacheline_aligned;
 };
 
@@ -149,9 +149,10 @@ static irqreturn_t adc108s102_trigger_handler(int irq, void *p)
 		goto out_notify;
 
 	/* Skip the dummy response in the first slot */
-	iio_push_to_buffers_with_timestamp(indio_dev,
-					   (u8 *)&st->rx_buf[1],
-					   iio_get_time_ns(indio_dev));
+	iio_push_to_buffers_with_ts_unaligned(indio_dev,
+					      &st->rx_buf[1],
+					      st->ring_xfer.len - sizeof(st->rx_buf[1]),
+					      iio_get_time_ns(indio_dev));
 
 out_notify:
 	iio_trigger_notify_done(indio_dev->trig);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 3/4] iio: gyro: mpu3050: Fix alignment and size issues with buffers.
  2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned() Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 2/4] iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio buffers Jonathan Cameron
@ 2021-06-13 15:10 ` Jonathan Cameron
  2021-06-13 15:10 ` [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements Jonathan Cameron
  2021-07-18 14:55 ` [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
  4 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-13 15:10 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

Fix a set of closely related issues.
1. When using fifo_values() there was not enough space for the timestamp to
   be inserted by iio_push_to_buffers_with_timestamp()
2. fifo_values() did not meet the alignment requirement of
   iio_push_to_buffers_with_timestamp()
3. hw_values did not meet the alignment requirement either.

1 and 2 fixed by using new iio_push_to_buffers_with_ts_unaligned() which has
no alignment or space padding requirements.
3 fixed by introducing a structure that makes the space and alignment
requirements explicit.

Fixes: 3904b28efb2c ("iio: gyro: Add driver for the MPU-3050 gyroscope")
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/iio/gyro/mpu3050-core.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 3225de1f023b..ea387efab62d 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -471,13 +471,10 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
 	int ret;
-	/*
-	 * Temperature 1*16 bits
-	 * Three axes 3*16 bits
-	 * Timestamp 64 bits (4*16 bits)
-	 * Sum total 8*16 bits
-	 */
-	__be16 hw_values[8];
+	struct {
+		__be16 chans[4];
+		s64 timestamp __aligned(8);
+	} scan;
 	s64 timestamp;
 	unsigned int datums_from_fifo = 0;
 
@@ -572,9 +569,10 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
 				fifo_values[4]);
 
 			/* Index past the footer (fifo_values[0]) and push */
-			iio_push_to_buffers_with_timestamp(indio_dev,
-							   &fifo_values[1],
-							   timestamp);
+			iio_push_to_buffers_with_ts_unaligned(indio_dev,
+							      &fifo_values[1],
+							      sizeof(__be16) * 4,
+							      timestamp);
 
 			fifocnt -= toread;
 			datums_from_fifo++;
@@ -632,15 +630,15 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
 		goto out_trigger_unlock;
 	}
 
-	ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H, &hw_values,
-			       sizeof(hw_values));
+	ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H, scan.chans,
+			       sizeof(scan.chans));
 	if (ret) {
 		dev_err(mpu3050->dev,
 			"error reading axis data\n");
 		goto out_trigger_unlock;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, hw_values, timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan, timestamp);
 
 out_trigger_unlock:
 	mutex_unlock(&mpu3050->lock);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements.
  2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
                   ` (2 preceding siblings ...)
  2021-06-13 15:10 ` [PATCH v2 3/4] iio: gyro: mpu3050: Fix alignment and size issues with buffers Jonathan Cameron
@ 2021-06-13 15:10 ` Jonathan Cameron
  2021-06-14  8:25   ` Sa, Nuno
  2021-07-18 14:55 ` [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
  4 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-13 15:10 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron, Nuno Sá

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

iio_push_to_buffers_with_timestamp() requires that the buffer
is 8 byte alignment to ensure an inserted timestamp is naturally aligned.

This requirement was not met here when burst mode is in use beause
of a leading u16. Use the new iio_push_to_buffers_with_ts_unaligned()
function that has more relaxed requirements.

It is somewhat complex to access that actual data length, but a
safe bound can be found by using scan_bytes - sizeof(timestamp) so that
is used in this path.

More efficient approaches exist, but this ensure correctness at the
cost of using a bounce buffer.

Fixes: 5075e0720d93 ("iio: imu: adis: generalize burst mode support")
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/iio/imu/adis16400.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index cb8d3ffab6fc..66a83ebd3109 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -648,13 +648,23 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
 	if (ret)
 		dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret);
 
-	if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
+	if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) {
 		buffer = adis->buffer + sizeof(u16);
-	else
-		buffer = adis->buffer;
+		/*
+		 * The size here is always larger than, or equal to the true
+		 * size of the channel data. This may result in a larger copy
+		 * than necessary, but as the target buffer will be
+		 * buffer->scan_bytes this will be safe.
+		 */
+		iio_push_to_buffers_with_ts_unaligned(indio_dev, buffer,
+						      indio_dev->scan_bytes - sizeof(pf->timestamp),
+						      pf->timestamp);
+	} else {
+		iio_push_to_buffers_with_timestamp(indio_dev,
+						   adis->buffer,
+						   pf->timestamp);
+	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
-		pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
 
-- 
2.32.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements.
  2021-06-13 15:10 ` [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements Jonathan Cameron
@ 2021-06-14  8:25   ` Sa, Nuno
  0 siblings, 0 replies; 9+ messages in thread
From: Sa, Nuno @ 2021-06-14  8:25 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio, Andy Shevchenko
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

> From: Jonathan Cameron <jic23@kernel.org>
> Sent: Sunday, June 13, 2021 5:11 PM
> To: linux-iio@vger.kernel.org; Andy Shevchenko
> <andy.shevchenko@gmail.com>; Sa, Nuno <Nuno.Sa@analog.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>; Jan Kiszka
> <jan.kiszka@siemens.com>; Jonathan Cameron
> <Jonathan.Cameron@huawei.com>; Sa, Nuno
> <Nuno.Sa@analog.com>
> Subject: [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment
> requirements.
> 
> [External]
> 
> From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> 
> iio_push_to_buffers_with_timestamp() requires that the buffer
> is 8 byte alignment to ensure an inserted timestamp is naturally
> aligned.
> 
> This requirement was not met here when burst mode is in use beause
> of a leading u16. Use the new
> iio_push_to_buffers_with_ts_unaligned()
> function that has more relaxed requirements.
> 
> It is somewhat complex to access that actual data length, but a
> safe bound can be found by using scan_bytes - sizeof(timestamp) so
> that
> is used in this path.
> 
> More efficient approaches exist, but this ensure correctness at the
> cost of using a bounce buffer.
> 
> Fixes: 5075e0720d93 ("iio: imu: adis: generalize burst mode support")
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Nuno Sá <nuno.sa@analog.com>
> ---
>  drivers/iio/imu/adis16400.c | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
> index cb8d3ffab6fc..66a83ebd3109 100644
> --- a/drivers/iio/imu/adis16400.c
> +++ b/drivers/iio/imu/adis16400.c
> @@ -648,13 +648,23 @@ static irqreturn_t
> adis16400_trigger_handler(int irq, void *p)
>  	if (ret)
>  		dev_err(&adis->spi->dev, "Failed to read data: %d\n",
> ret);
> 
> -	if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
> +	if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) {
>  		buffer = adis->buffer + sizeof(u16);
> -	else
> -		buffer = adis->buffer;
> +		/*
> +		 * The size here is always larger than, or equal to the
> true
> +		 * size of the channel data. This may result in a larger
> copy
> +		 * than necessary, but as the target buffer will be
> +		 * buffer->scan_bytes this will be safe.
> +		 */
> +		iio_push_to_buffers_with_ts_unaligned(indio_dev,
> buffer,
> +						      indio_dev-
> >scan_bytes - sizeof(pf->timestamp),
> +						      pf->timestamp);
> +	} else {
> +		iio_push_to_buffers_with_timestamp(indio_dev,
> +						   adis->buffer,
> +						   pf->timestamp);
> +	}
> 
> -	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
> -		pf->timestamp);
> 
>  	iio_trigger_notify_done(indio_dev->trig);
> 
> --
> 2.32.0

Reviewed-by: Nuno Sá <nuno.sa@analog.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
  2021-06-13 15:10 ` [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned() Jonathan Cameron
@ 2021-06-14  8:33   ` Sa, Nuno
  0 siblings, 0 replies; 9+ messages in thread
From: Sa, Nuno @ 2021-06-14  8:33 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio, Andy Shevchenko
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

> From: Jonathan Cameron <jic23@kernel.org>
> Sent: Sunday, June 13, 2021 5:11 PM
> To: linux-iio@vger.kernel.org; Andy Shevchenko
> <andy.shevchenko@gmail.com>; Sa, Nuno <Nuno.Sa@analog.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>; Jan Kiszka
> <jan.kiszka@siemens.com>; Jonathan Cameron
> <Jonathan.Cameron@huawei.com>
> Subject: [PATCH v2 1/4] iio: core: Introduce
> iio_push_to_buffers_with_ts_unaligned()
> 
> [External]
> 
> From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> 
> 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 <Jonathan.Cameron@huawei.com>
> ---
>  drivers/iio/industrialio-buffer.c | 46
> +++++++++++++++++++++++++++++++
>  include/linux/iio/buffer.h        |  4 +++
>  include/linux/iio/iio-opaque.h    |  4 +++
>  3 files changed, 54 insertions(+)
> 
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-
> buffer.c
> index fdd623407b96..5241b5a5c6c0 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -1730,6 +1730,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);

Well, As I said in the RFC: "I still feel that if we are taking the data_sz parameter on
the API, we should handle it more strictly. But I do not feel too strong about this (as
you said, It's not expected to exist too much users of this)..." :). And we can always
become more "strict" if we start to see people doing really bad things... So, as you
said, most likely we won't have much benefit from the added complexity.

Being this said:

Reviewed-by: Nuno Sá <nuno.sa@analog.com>

- Nuno Sá

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases.
  2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
                   ` (3 preceding siblings ...)
  2021-06-13 15:10 ` [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements Jonathan Cameron
@ 2021-07-18 14:55 ` Jonathan Cameron
  2021-10-03 15:54   ` Jonathan Cameron
  4 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2021-07-18 14:55 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

On Sun, 13 Jun 2021 16:10:35 +0100
Jonathan Cameron <jic23@kernel.org> wrote:

> From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Hi All,

If anyone has time to take a look at this, particularly the first patch which
does the interesting stuff and patch 3 which I don't think has had any review
yet that would be great.

Thanks,

Jonathan

> 
> Thanks to Andy and Nuno for reviews.
> 
> Chances since V1/RFC:
> * Renamed the function to iio_push_to_buffer_with_ts_unaligned()
> * Fixed the various bugs people pointed out.
> * Used more standard realloc handling to be more 'obviously' correct.
> * Added some additional comments on the sizing of the copy to explain why
>   it is a conservative estimate and may copy more than strictly necessary.
> 
> A few things we discussed I didn't do (for now)...
> 
> I decided against adding explicit bounce buffer allocation calls for now,
> though I'm open to doing that in future if we find doing the somewhat hidden
> realloc to be a problem.
> 
> I haven't computed a more precise data_sz as I don't thing the benefits
> of a more precise copy or not passing the size, make it worth the slight
> reduction in complexity for the callers.  Again, open to revisiting this
> in future!
> 
> I tested it by hacking the dummy driver to shift it's data by one
> byte and call iio_push_to_buffers_with_ts_unaligned().
> 
> Strictly a hack. I definitely don't want to move this driver over to this
> new interface as it might encourage inappropriate use.
> 
> diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
> index 59aa60d4ca37..b47af7df8efc 100644
> --- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
> +++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
> @@ -19,6 +19,7 @@
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/trigger_consumer.h>
>  #include <linux/iio/triggered_buffer.h>
> +#include <asm/unaligned.h>
>  
>  #include "iio_simple_dummy.h"
>  
> @@ -78,12 +79,13 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
>                         j = find_next_bit(indio_dev->active_scan_mask,
>                                           indio_dev->masklength, j);
>                         /* random access read from the 'device' */
> -                       data[i] = fakedata[j];
> +//                     data[i] = fakedata[j];
> +                       put_unaligned_le16(fakedata[j], ((u8 *)(&data[i])) + 1);
>                         len += 2;
>                 }
>         }
>  
> -       iio_push_to_buffers_with_timestamp(indio_dev, data,
> +       iio_push_to_buffers_with_ts_unaligned(indio_dev, ((u8 *)(data)) + 1, indio_dev->scan_bytes - 8,
>                                            iio_get_time_ns(indio_dev));
> 
> 
> v1 description:
> 
> I finally got around to do a manual audit of all the calls to
> iio_push_to_buffers_with_timestamp() which has the somewhat odd requirements
> of:
> 1. 8 byte alignment of the provided buffer.
> 2. space for an 8 byte naturally aligned timestamp to be inserted at the
>    end.
> 
> Unfortunately there were rather a lot of these left, but time to bite the bullet
> and clean them up.
> 
> As discussed previous in
> https://lore.kernel.org/linux-iio/20200920112742.170751-1-jic23@kernel.org/
> it is not easy to fix the alignment issue without requiring a bounce buffer.
> This final part of the 4 sets of fixes is concerned with the cases where
> bounce buffers are the proposed solutions.
> 
> In these cases we have hardware that reads a prefix that we wish to
> drop. That makes it hard to directly read the data into the correct location.
> 
> Rather than implementing bouce buffers in each case, this set provides some
> magic in the core to handle them via a new function.
> iio_push_to_buffers_with_ts_na() - non aligned
> 
> Note this is totally untested as I don't have suitable hardware or emulation.
> I can fake something up in the dummy driver or via QEMU but I definitely want
> both eyes and testing on this series!
> 
> Jonathan Cameron (4):
>   iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
>   iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio
>     buffers.
>   iio: gyro: mpu3050: Fix alignment and size issues with buffers.
>   iio: imu: adis16400: Fix buffer alignment requirements.
> 
>  drivers/iio/adc/ti-adc108s102.c   | 11 ++++----
>  drivers/iio/gyro/mpu3050-core.c   | 24 ++++++++--------
>  drivers/iio/imu/adis16400.c       | 20 ++++++++++----
>  drivers/iio/industrialio-buffer.c | 46 +++++++++++++++++++++++++++++++
>  include/linux/iio/buffer.h        |  4 +++
>  include/linux/iio/iio-opaque.h    |  4 +++
>  6 files changed, 86 insertions(+), 23 deletions(-)
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases.
  2021-07-18 14:55 ` [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
@ 2021-10-03 15:54   ` Jonathan Cameron
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2021-10-03 15:54 UTC (permalink / raw)
  To: linux-iio, Andy Shevchenko, Nuno Sa
  Cc: Linus Walleij, Jan Kiszka, Jonathan Cameron

On Sun, 18 Jul 2021 15:55:59 +0100
Jonathan Cameron <jic23@kernel.org> wrote:

> On Sun, 13 Jun 2021 16:10:35 +0100
> Jonathan Cameron <jic23@kernel.org> wrote:
> 
> > From: Jonathan Cameron <Jonathan.Cameron@huawei.com>  
> Hi All,
> 
> If anyone has time to take a look at this, particularly the first patch which
> does the interesting stuff and patch 3 which I don't think has had any review
> yet that would be great.

It might have helped if I'd identified patch 2 as the one that was
missing reviews.  Ah well. I've done something I really dislike doing and
given up on getting a review for that patch.  As such I've applied
this series to the togreg branch of iio.git and pushed it out as testing for
0-day to see if it can find anything we missed.

If anyone has a chance to sanity check patch 2 for any idiocy on my part it
would still be very much appreciated!

Thanks to Nuno, Andy and Linus for their reviews of this fiddly series.

Thanks,

Jonathan

> 
> Thanks,
> 
> Jonathan
> 
> > 
> > Thanks to Andy and Nuno for reviews.
> > 
> > Chances since V1/RFC:
> > * Renamed the function to iio_push_to_buffer_with_ts_unaligned()
> > * Fixed the various bugs people pointed out.
> > * Used more standard realloc handling to be more 'obviously' correct.
> > * Added some additional comments on the sizing of the copy to explain why
> >   it is a conservative estimate and may copy more than strictly necessary.
> > 
> > A few things we discussed I didn't do (for now)...
> > 
> > I decided against adding explicit bounce buffer allocation calls for now,
> > though I'm open to doing that in future if we find doing the somewhat hidden
> > realloc to be a problem.
> > 
> > I haven't computed a more precise data_sz as I don't thing the benefits
> > of a more precise copy or not passing the size, make it worth the slight
> > reduction in complexity for the callers.  Again, open to revisiting this
> > in future!
> > 
> > I tested it by hacking the dummy driver to shift it's data by one
> > byte and call iio_push_to_buffers_with_ts_unaligned().
> > 
> > Strictly a hack. I definitely don't want to move this driver over to this
> > new interface as it might encourage inappropriate use.
> > 
> > diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
> > index 59aa60d4ca37..b47af7df8efc 100644
> > --- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
> > +++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
> > @@ -19,6 +19,7 @@
> >  #include <linux/iio/buffer.h>
> >  #include <linux/iio/trigger_consumer.h>
> >  #include <linux/iio/triggered_buffer.h>
> > +#include <asm/unaligned.h>
> >  
> >  #include "iio_simple_dummy.h"
> >  
> > @@ -78,12 +79,13 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
> >                         j = find_next_bit(indio_dev->active_scan_mask,
> >                                           indio_dev->masklength, j);
> >                         /* random access read from the 'device' */
> > -                       data[i] = fakedata[j];
> > +//                     data[i] = fakedata[j];
> > +                       put_unaligned_le16(fakedata[j], ((u8 *)(&data[i])) + 1);
> >                         len += 2;
> >                 }
> >         }
> >  
> > -       iio_push_to_buffers_with_timestamp(indio_dev, data,
> > +       iio_push_to_buffers_with_ts_unaligned(indio_dev, ((u8 *)(data)) + 1, indio_dev->scan_bytes - 8,
> >                                            iio_get_time_ns(indio_dev));
> > 
> > 
> > v1 description:
> > 
> > I finally got around to do a manual audit of all the calls to
> > iio_push_to_buffers_with_timestamp() which has the somewhat odd requirements
> > of:
> > 1. 8 byte alignment of the provided buffer.
> > 2. space for an 8 byte naturally aligned timestamp to be inserted at the
> >    end.
> > 
> > Unfortunately there were rather a lot of these left, but time to bite the bullet
> > and clean them up.
> > 
> > As discussed previous in
> > https://lore.kernel.org/linux-iio/20200920112742.170751-1-jic23@kernel.org/
> > it is not easy to fix the alignment issue without requiring a bounce buffer.
> > This final part of the 4 sets of fixes is concerned with the cases where
> > bounce buffers are the proposed solutions.
> > 
> > In these cases we have hardware that reads a prefix that we wish to
> > drop. That makes it hard to directly read the data into the correct location.
> > 
> > Rather than implementing bouce buffers in each case, this set provides some
> > magic in the core to handle them via a new function.
> > iio_push_to_buffers_with_ts_na() - non aligned
> > 
> > Note this is totally untested as I don't have suitable hardware or emulation.
> > I can fake something up in the dummy driver or via QEMU but I definitely want
> > both eyes and testing on this series!
> > 
> > Jonathan Cameron (4):
> >   iio: core: Introduce iio_push_to_buffers_with_ts_unaligned()
> >   iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio
> >     buffers.
> >   iio: gyro: mpu3050: Fix alignment and size issues with buffers.
> >   iio: imu: adis16400: Fix buffer alignment requirements.
> > 
> >  drivers/iio/adc/ti-adc108s102.c   | 11 ++++----
> >  drivers/iio/gyro/mpu3050-core.c   | 24 ++++++++--------
> >  drivers/iio/imu/adis16400.c       | 20 ++++++++++----
> >  drivers/iio/industrialio-buffer.c | 46 +++++++++++++++++++++++++++++++
> >  include/linux/iio/buffer.h        |  4 +++
> >  include/linux/iio/iio-opaque.h    |  4 +++
> >  6 files changed, 86 insertions(+), 23 deletions(-)
> >   
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-10-03 15:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-13 15:10 [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
2021-06-13 15:10 ` [PATCH v2 1/4] iio: core: Introduce iio_push_to_buffers_with_ts_unaligned() Jonathan Cameron
2021-06-14  8:33   ` Sa, Nuno
2021-06-13 15:10 ` [PATCH v2 2/4] iio: adc: ti-adc108s102: Fix alignment of buffer pushed to iio buffers Jonathan Cameron
2021-06-13 15:10 ` [PATCH v2 3/4] iio: gyro: mpu3050: Fix alignment and size issues with buffers Jonathan Cameron
2021-06-13 15:10 ` [PATCH v2 4/4] iio: imu: adis16400: Fix buffer alignment requirements Jonathan Cameron
2021-06-14  8:25   ` Sa, Nuno
2021-07-18 14:55 ` [PATCH v2 0/4] IIO: Alignment fixes part 4 - bounce buffers for the hard cases Jonathan Cameron
2021-10-03 15:54   ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.