linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper
@ 2020-04-01 12:59 Alexandru Ardelean
  2020-04-01 12:59 ` [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward Alexandru Ardelean
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Alexandru Ardelean @ 2020-04-01 12:59 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devel
  Cc: jic23, knaack.h, lars, pmeerw, lorenzo.bianconi83, Alexandru Ardelean

This change adds the iio_device_attach_kfifo_buffer() helper/short-hand,
which groups the simple routine of allocating a kfifo buffers via
devm_iio_kfifo_allocate() and calling iio_device_attach_buffer().

The mode_flags parameter is required. The setup_ops parameter is optional.

This function will be a bit more useful when needing to define multiple
buffers per IIO device.

One requirement [that is more a recommendation] for this helper, is to call
it after 'indio_dev' has been populated.

Also, one consequence related to using this helper is that the resource
management of the buffer will be tied to 'indio_dev->dev'. Previously it
was open-coded, and each driver does it slightly differently. Most of them
tied it to the parent device, some of them to 'indio_dev->dev'.
This shouldn't be a problem, and may be a good idea when adding more
buffers per-device.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/iio/buffer/kfifo_buf.c | 37 ++++++++++++++++++++++++++++++++++
 include/linux/iio/kfifo_buf.h  |  4 ++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index 3150f8ab984b..05b7c5fc6f1d 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -228,4 +228,41 @@ void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
 }
 EXPORT_SYMBOL(devm_iio_kfifo_free);
 
+/**
+ * iio_device_attach_kfifo_buffer - Allocate a kfifo buffer & attach it to an IIO device
+ * @indio_dev: The device the buffer should be attached to
+ * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE and/or
+ *		INDIO_BUFFER_TRIGGERED).
+ * @setup_ops: The setup_ops required to configure the HW part of the buffer (optional)
+ *
+ * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
+ * attaches it to the IIO device via iio_device_attach_buffer().
+ * This is meant to be a bit of a short-hand/helper function as many driver
+ * seem to do this.
+ */
+int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
+				   int mode_flags,
+				   const struct iio_buffer_setup_ops *setup_ops)
+{
+	struct iio_buffer *buffer;
+
+	if (mode_flags)
+		mode_flags &= kfifo_access_funcs.modes;
+
+	if (!mode_flags)
+		return -EINVAL;
+
+	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
+	if (!buffer)
+		return -ENOMEM;
+
+	iio_device_attach_buffer(indio_dev, buffer);
+
+	indio_dev->modes |= mode_flags;
+	indio_dev->setup_ops = setup_ops;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iio_device_attach_kfifo_buffer);
+
 MODULE_LICENSE("GPL");
diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
index 764659e01b68..2363a931be14 100644
--- a/include/linux/iio/kfifo_buf.h
+++ b/include/linux/iio/kfifo_buf.h
@@ -11,4 +11,8 @@ void iio_kfifo_free(struct iio_buffer *r);
 struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev);
 void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r);
 
+int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
+				   int mode_flags,
+				   const struct iio_buffer_setup_ops *setup_ops);
+
 #endif
-- 
2.17.1


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

* [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward
  2020-04-01 12:59 [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
@ 2020-04-01 12:59 ` Alexandru Ardelean
  2020-04-05 10:44   ` Jonathan Cameron
  2020-04-01 12:59 ` [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
  2020-04-05 10:46 ` [PATCH 1/3] iio: kfifo: add " Jonathan Cameron
  2 siblings, 1 reply; 9+ messages in thread
From: Alexandru Ardelean @ 2020-04-01 12:59 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devel
  Cc: jic23, knaack.h, lars, pmeerw, lorenzo.bianconi83, Alexandru Ardelean

All drivers that already call devm_iio_kfifo_allocate() &
iio_device_attach_buffer() are simple to convert to
iio_device_attach_kfifo_buffer() in a single go/patch/.

This change does that.

For drivers max30100 & max30102 this helper is called after indio_dev has
been populated. This doesn't make any difference [at this point in time].

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/iio/accel/sca3000.c                    | 18 ++----------------
 drivers/iio/accel/ssp_accel_sensor.c           | 13 ++++---------
 drivers/iio/adc/ina2xx-adc.c                   | 13 +++++--------
 drivers/iio/gyro/ssp_gyro_sensor.c             | 13 ++++---------
 drivers/iio/health/max30100.c                  | 15 ++++++---------
 drivers/iio/health/max30102.c                  | 15 ++++++---------
 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 17 +++++++----------
 drivers/iio/light/acpi-als.c                   | 11 +++++------
 drivers/iio/light/apds9960.c                   | 15 ++++++---------
 9 files changed, 45 insertions(+), 85 deletions(-)

diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 66d768d971e1..a0db76082ba6 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -1272,20 +1272,6 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
 	return ret;
 }
 
-static int sca3000_configure_ring(struct iio_dev *indio_dev)
-{
-	struct iio_buffer *buffer;
-
-	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
-
-	return 0;
-}
-
 static inline
 int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
 {
@@ -1480,7 +1466,8 @@ static int sca3000_probe(struct spi_device *spi)
 	}
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = sca3000_configure_ring(indio_dev);
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &sca3000_ring_setup_ops);
 	if (ret)
 		return ret;
 
@@ -1494,7 +1481,6 @@ static int sca3000_probe(struct spi_device *spi)
 		if (ret)
 			return ret;
 	}
-	indio_dev->setup_ops = &sca3000_ring_setup_ops;
 	ret = sca3000_clean_setup(st);
 	if (ret)
 		goto error_free_irq;
diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c
index c32647abce20..1d9971db949d 100644
--- a/drivers/iio/accel/ssp_accel_sensor.c
+++ b/drivers/iio/accel/ssp_accel_sensor.c
@@ -96,7 +96,6 @@ static int ssp_accel_probe(struct platform_device *pdev)
 	int ret;
 	struct iio_dev *indio_dev;
 	struct ssp_sensor_data *spd;
-	struct iio_buffer *buffer;
 
 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
 	if (!indio_dev)
@@ -111,18 +110,14 @@ static int ssp_accel_probe(struct platform_device *pdev)
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->dev.of_node = pdev->dev.of_node;
 	indio_dev->info = &ssp_accel_iio_info;
-	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
 	indio_dev->channels = ssp_acc_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels);
 	indio_dev->available_scan_masks = ssp_accel_scan_mask;
 
-	buffer = devm_iio_kfifo_allocate(&pdev->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
-	indio_dev->setup_ops = &ssp_accel_buffer_ops;
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &ssp_accel_buffer_ops);
+	if (ret)
+		return ret;
 
 	platform_set_drvdata(pdev, indio_dev);
 
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index bdd7cba6f6b0..2070809e1acc 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -950,7 +950,6 @@ static int ina2xx_probe(struct i2c_client *client,
 {
 	struct ina2xx_chip_info *chip;
 	struct iio_dev *indio_dev;
-	struct iio_buffer *buffer;
 	unsigned int val;
 	enum ina2xx_ids type;
 	int ret;
@@ -1014,7 +1013,7 @@ static int ina2xx_probe(struct i2c_client *client,
 		return ret;
 	}
 
-	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->dev.of_node = client->dev.of_node;
 	if (id->driver_data == ina226) {
@@ -1027,13 +1026,11 @@ static int ina2xx_probe(struct i2c_client *client,
 		indio_dev->info = &ina219_info;
 	}
 	indio_dev->name = id->name;
-	indio_dev->setup_ops = &ina2xx_setup_ops;
 
-	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &ina2xx_setup_ops);
+	if (ret)
+		return ret;
 
 	return iio_device_register(indio_dev);
 }
diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c
index 4e4ee4167544..c12d3db5a951 100644
--- a/drivers/iio/gyro/ssp_gyro_sensor.c
+++ b/drivers/iio/gyro/ssp_gyro_sensor.c
@@ -96,7 +96,6 @@ static int ssp_gyro_probe(struct platform_device *pdev)
 	int ret;
 	struct iio_dev *indio_dev;
 	struct ssp_sensor_data *spd;
-	struct iio_buffer *buffer;
 
 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
 	if (!indio_dev)
@@ -110,18 +109,14 @@ static int ssp_gyro_probe(struct platform_device *pdev)
 	indio_dev->name = ssp_gyro_name;
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->info = &ssp_gyro_iio_info;
-	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
 	indio_dev->channels = ssp_gyro_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ssp_gyro_channels);
 	indio_dev->available_scan_masks = ssp_gyro_scan_mask;
 
-	buffer = devm_iio_kfifo_allocate(&pdev->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
-	indio_dev->setup_ops = &ssp_gyro_buffer_ops;
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &ssp_gyro_buffer_ops);
+	if (ret)
+		return ret;
 
 	platform_set_drvdata(pdev, indio_dev);
 
diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c
index 546fc37ad75d..f4e9866f4c3d 100644
--- a/drivers/iio/health/max30100.c
+++ b/drivers/iio/health/max30100.c
@@ -418,7 +418,6 @@ static int max30100_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
 	struct max30100_data *data;
-	struct iio_buffer *buffer;
 	struct iio_dev *indio_dev;
 	int ret;
 
@@ -426,21 +425,19 @@ static int max30100_probe(struct i2c_client *client,
 	if (!indio_dev)
 		return -ENOMEM;
 
-	buffer = devm_iio_kfifo_allocate(&client->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
 	indio_dev->name = MAX30100_DRV_NAME;
 	indio_dev->channels = max30100_channels;
 	indio_dev->info = &max30100_info;
 	indio_dev->num_channels = ARRAY_SIZE(max30100_channels);
 	indio_dev->available_scan_masks = max30100_scan_masks;
-	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
-	indio_dev->setup_ops = &max30100_buffer_setup_ops;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->dev.parent = &client->dev;
 
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &max30100_buffer_setup_ops);
+	if (ret)
+		return ret;
+
 	data = iio_priv(indio_dev);
 	data->indio_dev = indio_dev;
 	data->client = client;
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 74fc260b957e..e15126d23dfb 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -507,7 +507,6 @@ static int max30102_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
 	struct max30102_data *data;
-	struct iio_buffer *buffer;
 	struct iio_dev *indio_dev;
 	int ret;
 	unsigned int reg;
@@ -516,16 +515,9 @@ static int max30102_probe(struct i2c_client *client,
 	if (!indio_dev)
 		return -ENOMEM;
 
-	buffer = devm_iio_kfifo_allocate(&client->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
 	indio_dev->name = MAX30102_DRV_NAME;
 	indio_dev->info = &max30102_info;
-	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
-	indio_dev->setup_ops = &max30102_buffer_setup_ops;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->dev.parent = &client->dev;
 
 	data = iio_priv(indio_dev);
@@ -551,6 +543,11 @@ static int max30102_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &max30102_buffer_setup_ops);
+	if (ret)
+		return ret;
+
 	data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
 	if (IS_ERR(data->regmap)) {
 		dev_err(&client->dev, "regmap initialization failed\n");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index bb899345f2bb..4ba3d5551570 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -30,8 +30,8 @@
  * Denis Ciocca <denis.ciocca@st.com>
  */
 #include <linux/module.h>
-#include <linux/iio/kfifo_buf.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
 #include <linux/iio/buffer.h>
 #include <linux/regmap.h>
 #include <linux/bitfield.h>
@@ -713,20 +713,17 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
 
 int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
 {
-	struct iio_buffer *buffer;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
 		if (!hw->iio_devs[i])
 			continue;
 
-		buffer = devm_iio_kfifo_allocate(hw->dev);
-		if (!buffer)
-			return -ENOMEM;
-
-		iio_device_attach_buffer(hw->iio_devs[i], buffer);
-		hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
-		hw->iio_devs[i]->setup_ops = &st_lsm6dsx_buffer_ops;
+		ret = iio_device_attach_kfifo_buffer(hw->iio_devs[i],
+						     INDIO_BUFFER_SOFTWARE,
+						     &st_lsm6dsx_buffer_ops);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c
index 1eafd0b24e18..ea99705c3387 100644
--- a/drivers/iio/light/acpi-als.c
+++ b/drivers/iio/light/acpi-als.c
@@ -166,6 +166,7 @@ static int acpi_als_add(struct acpi_device *device)
 	struct acpi_als *als;
 	struct iio_dev *indio_dev;
 	struct iio_buffer *buffer;
+	int ret;
 
 	indio_dev = devm_iio_device_alloc(&device->dev, sizeof(*als));
 	if (!indio_dev)
@@ -180,15 +181,13 @@ static int acpi_als_add(struct acpi_device *device)
 	indio_dev->name = ACPI_ALS_DEVICE_NAME;
 	indio_dev->dev.parent = &device->dev;
 	indio_dev->info = &acpi_als_info;
-	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
 	indio_dev->channels = acpi_als_channels;
 	indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels);
 
-	buffer = devm_iio_kfifo_allocate(&device->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     NULL);
+	if (ret)
+		return ret;
 
 	return devm_iio_device_register(&device->dev, indio_dev);
 }
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 52f86bc777dd..8acc319445b6 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -987,7 +987,6 @@ static int apds9960_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
 	struct apds9960_data *data;
-	struct iio_buffer *buffer;
 	struct iio_dev *indio_dev;
 	int ret;
 
@@ -995,20 +994,18 @@ static int apds9960_probe(struct i2c_client *client,
 	if (!indio_dev)
 		return -ENOMEM;
 
-	buffer = devm_iio_kfifo_allocate(&client->dev);
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->info = &apds9960_info;
 	indio_dev->name = APDS9960_DRV_NAME;
 	indio_dev->channels = apds9960_channels;
 	indio_dev->num_channels = ARRAY_SIZE(apds9960_channels);
 	indio_dev->available_scan_masks = apds9960_scan_masks;
-	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
-	indio_dev->setup_ops = &apds9960_buffer_setup_ops;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &apds9960_buffer_setup_ops);
+	if (ret)
+		return ret;
 
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
-- 
2.17.1


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

* [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper
  2020-04-01 12:59 [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
  2020-04-01 12:59 ` [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward Alexandru Ardelean
@ 2020-04-01 12:59 ` Alexandru Ardelean
  2020-04-05 10:49   ` Jonathan Cameron
  2020-04-05 10:46 ` [PATCH 1/3] iio: kfifo: add " Jonathan Cameron
  2 siblings, 1 reply; 9+ messages in thread
From: Alexandru Ardelean @ 2020-04-01 12:59 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devel
  Cc: jic23, knaack.h, lars, pmeerw, lorenzo.bianconi83, Alexandru Ardelean

This driver calls iio_kfifo_allocate() vs devm_iio_kfifo_allocate(). But
the conversion is still simpler here, and cleans-up/reduces some error
paths.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 .../staging/iio/impedance-analyzer/ad5933.c   | 28 ++++---------------
 1 file changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index af0bcf95ee8a..7bde93c6dd74 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -602,22 +602,6 @@ static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = {
 	.postdisable = ad5933_ring_postdisable,
 };
 
-static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	struct iio_buffer *buffer;
-
-	buffer = iio_kfifo_allocate();
-	if (!buffer)
-		return -ENOMEM;
-
-	iio_device_attach_buffer(indio_dev, buffer);
-
-	/* Ring buffer functions - here trigger setup related */
-	indio_dev->setup_ops = &ad5933_ring_setup_ops;
-
-	return 0;
-}
-
 static void ad5933_work(struct work_struct *work)
 {
 	struct ad5933_state *st = container_of(work,
@@ -738,26 +722,25 @@ static int ad5933_probe(struct i2c_client *client,
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->info = &ad5933_info;
 	indio_dev->name = id->name;
-	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->channels = ad5933_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
 
-	ret = ad5933_register_ring_funcs_and_init(indio_dev);
+	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
+					     &ad5933_ring_setup_ops);
 	if (ret)
 		goto error_disable_mclk;
 
 	ret = ad5933_setup(st);
 	if (ret)
-		goto error_unreg_ring;
+		goto error_disable_mclk;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_unreg_ring;
+		goto error_disable_mclk;
 
 	return 0;
 
-error_unreg_ring:
-	iio_kfifo_free(indio_dev->buffer);
 error_disable_mclk:
 	clk_disable_unprepare(st->mclk);
 error_disable_reg:
@@ -772,7 +755,6 @@ static int ad5933_remove(struct i2c_client *client)
 	struct ad5933_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	iio_kfifo_free(indio_dev->buffer);
 	regulator_disable(st->reg);
 	clk_disable_unprepare(st->mclk);
 
-- 
2.17.1


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

* Re: [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward
  2020-04-01 12:59 ` [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward Alexandru Ardelean
@ 2020-04-05 10:44   ` Jonathan Cameron
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2020-04-05 10:44 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-kernel, devel, knaack.h, lars, pmeerw,
	lorenzo.bianconi83

On Wed, 1 Apr 2020 15:59:35 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> All drivers that already call devm_iio_kfifo_allocate() &
> iio_device_attach_buffer() are simple to convert to
> iio_device_attach_kfifo_buffer() in a single go/patch/.
> 
> This change does that.
> 
> For drivers max30100 & max30102 this helper is called after indio_dev has
> been populated. This doesn't make any difference [at this point in time].
> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>

Comments inline refer back to the question of whether this results in
any order changes that might matter.  Unfortunately it does. I think
we need to allow the new function to take the struct device *
that the driver author wants it to us and to have the naming make it
clear it's a managed function.

The alternative is to go tidy up the allocations so all of the managed
calls scopes are correct.  I.e. any that are associated with the iio_dev
(or iio_priv obviously) use the indio_dev->dev including irq requests
etc.  That might be a good exercise to do but it's not a small one
and the benefits aren't obvious.  We'd move from a simple linear unwind
to a nested one.

devm_iio_device_alloc
devm_iio_*_alloc
devm_request_threaded_irq etc
devm_kzalloc
devm_iio_device_register

devm_iio_device_alloc
	devm_iio*alloc
	devm_request_threaded_irq
	devm_kzalloc
	devm_iio_device_register

So the release of the parent in the second cause the unwind of the
device setup in devm_iio_device_alloc and take out all of the items below.

If we'd structure this right in the first place the second option might be
more elegant but we didn't so retrofitting it now will be messy.

Jonathan

> ---
>  drivers/iio/accel/sca3000.c                    | 18 ++----------------
>  drivers/iio/accel/ssp_accel_sensor.c           | 13 ++++---------
>  drivers/iio/adc/ina2xx-adc.c                   | 13 +++++--------
>  drivers/iio/gyro/ssp_gyro_sensor.c             | 13 ++++---------
>  drivers/iio/health/max30100.c                  | 15 ++++++---------
>  drivers/iio/health/max30102.c                  | 15 ++++++---------
>  drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 17 +++++++----------
>  drivers/iio/light/acpi-als.c                   | 11 +++++------
>  drivers/iio/light/apds9960.c                   | 15 ++++++---------
>  9 files changed, 45 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
> index 66d768d971e1..a0db76082ba6 100644
> --- a/drivers/iio/accel/sca3000.c
> +++ b/drivers/iio/accel/sca3000.c
> @@ -1272,20 +1272,6 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> -static int sca3000_configure_ring(struct iio_dev *indio_dev)
> -{
> -	struct iio_buffer *buffer;
> -
> -	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
> -
> -	return 0;
> -}
> -
>  static inline
>  int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
>  {
> @@ -1480,7 +1466,8 @@ static int sca3000_probe(struct spi_device *spi)
>  	}
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  
> -	ret = sca3000_configure_ring(indio_dev);
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &sca3000_ring_setup_ops);

This one is fine (for a moment I thought we had a bug in the current code)
as this call is the next thing that needs unwinding after the devm_iio_device_alloc
anyway.  It would however have been more consistent if original code had
used the parent dev.

>  	if (ret)
>  		return ret;
>  
> @@ -1494,7 +1481,6 @@ static int sca3000_probe(struct spi_device *spi)
>  		if (ret)
>  			return ret;
>  	}
> -	indio_dev->setup_ops = &sca3000_ring_setup_ops;
>  	ret = sca3000_clean_setup(st);
>  	if (ret)
>  		goto error_free_irq;
> diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c
> index c32647abce20..1d9971db949d 100644
> --- a/drivers/iio/accel/ssp_accel_sensor.c
> +++ b/drivers/iio/accel/ssp_accel_sensor.c
> @@ -96,7 +96,6 @@ static int ssp_accel_probe(struct platform_device *pdev)
>  	int ret;
>  	struct iio_dev *indio_dev;
>  	struct ssp_sensor_data *spd;
> -	struct iio_buffer *buffer;
>  
>  	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
>  	if (!indio_dev)
> @@ -111,18 +110,14 @@ static int ssp_accel_probe(struct platform_device *pdev)
>  	indio_dev->dev.parent = &pdev->dev;
>  	indio_dev->dev.of_node = pdev->dev.of_node;
>  	indio_dev->info = &ssp_accel_iio_info;
> -	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
>  	indio_dev->channels = ssp_acc_channels;
>  	indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels);
>  	indio_dev->available_scan_masks = ssp_accel_scan_mask;
>  
> -	buffer = devm_iio_kfifo_allocate(&pdev->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
> -	indio_dev->setup_ops = &ssp_accel_buffer_ops;
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &ssp_accel_buffer_ops);
> +	if (ret)
> +		return ret;
>  
>  	platform_set_drvdata(pdev, indio_dev);
>  
> diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
> index bdd7cba6f6b0..2070809e1acc 100644
> --- a/drivers/iio/adc/ina2xx-adc.c
> +++ b/drivers/iio/adc/ina2xx-adc.c
> @@ -950,7 +950,6 @@ static int ina2xx_probe(struct i2c_client *client,
>  {
>  	struct ina2xx_chip_info *chip;
>  	struct iio_dev *indio_dev;
> -	struct iio_buffer *buffer;
>  	unsigned int val;
>  	enum ina2xx_ids type;
>  	int ret;
> @@ -1014,7 +1013,7 @@ static int ina2xx_probe(struct i2c_client *client,
>  		return ret;
>  	}
>  
> -	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->dev.of_node = client->dev.of_node;
>  	if (id->driver_data == ina226) {
> @@ -1027,13 +1026,11 @@ static int ina2xx_probe(struct i2c_client *client,
>  		indio_dev->info = &ina219_info;
>  	}
>  	indio_dev->name = id->name;
> -	indio_dev->setup_ops = &ina2xx_setup_ops;
>  
> -	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &ina2xx_setup_ops);
> +	if (ret)
> +		return ret;

This changes the unwind order.  Not good from an obviously correct point of
view.

>  
>  	return iio_device_register(indio_dev);
>  }
> diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c
> index 4e4ee4167544..c12d3db5a951 100644
> --- a/drivers/iio/gyro/ssp_gyro_sensor.c
> +++ b/drivers/iio/gyro/ssp_gyro_sensor.c
> @@ -96,7 +96,6 @@ static int ssp_gyro_probe(struct platform_device *pdev)
>  	int ret;
>  	struct iio_dev *indio_dev;
>  	struct ssp_sensor_data *spd;
> -	struct iio_buffer *buffer;
>  
>  	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
>  	if (!indio_dev)
> @@ -110,18 +109,14 @@ static int ssp_gyro_probe(struct platform_device *pdev)
>  	indio_dev->name = ssp_gyro_name;
>  	indio_dev->dev.parent = &pdev->dev;
>  	indio_dev->info = &ssp_gyro_iio_info;
> -	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
>  	indio_dev->channels = ssp_gyro_channels;
>  	indio_dev->num_channels = ARRAY_SIZE(ssp_gyro_channels);
>  	indio_dev->available_scan_masks = ssp_gyro_scan_mask;
>  
> -	buffer = devm_iio_kfifo_allocate(&pdev->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
> -	indio_dev->setup_ops = &ssp_gyro_buffer_ops;
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &ssp_gyro_buffer_ops);
> +	if (ret)
> +		return ret;
>  
>  	platform_set_drvdata(pdev, indio_dev);
>  
> diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c
> index 546fc37ad75d..f4e9866f4c3d 100644
> --- a/drivers/iio/health/max30100.c
> +++ b/drivers/iio/health/max30100.c
> @@ -418,7 +418,6 @@ static int max30100_probe(struct i2c_client *client,
>  			  const struct i2c_device_id *id)
>  {
>  	struct max30100_data *data;
> -	struct iio_buffer *buffer;
>  	struct iio_dev *indio_dev;
>  	int ret;
>  
> @@ -426,21 +425,19 @@ static int max30100_probe(struct i2c_client *client,
>  	if (!indio_dev)
>  		return -ENOMEM;
>  
> -	buffer = devm_iio_kfifo_allocate(&client->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
>  	indio_dev->name = MAX30100_DRV_NAME;
>  	indio_dev->channels = max30100_channels;
>  	indio_dev->info = &max30100_info;
>  	indio_dev->num_channels = ARRAY_SIZE(max30100_channels);
>  	indio_dev->available_scan_masks = max30100_scan_masks;
> -	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> -	indio_dev->setup_ops = &max30100_buffer_setup_ops;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->dev.parent = &client->dev;
>  
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &max30100_buffer_setup_ops);
> +	if (ret)
> +		return ret;
> +
>  	data = iio_priv(indio_dev);
>  	data->indio_dev = indio_dev;
>  	data->client = client;
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 74fc260b957e..e15126d23dfb 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -507,7 +507,6 @@ static int max30102_probe(struct i2c_client *client,
>  			  const struct i2c_device_id *id)
>  {
>  	struct max30102_data *data;
> -	struct iio_buffer *buffer;
>  	struct iio_dev *indio_dev;
>  	int ret;
>  	unsigned int reg;
> @@ -516,16 +515,9 @@ static int max30102_probe(struct i2c_client *client,
>  	if (!indio_dev)
>  		return -ENOMEM;
>  
> -	buffer = devm_iio_kfifo_allocate(&client->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
>  	indio_dev->name = MAX30102_DRV_NAME;
>  	indio_dev->info = &max30102_info;
> -	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> -	indio_dev->setup_ops = &max30102_buffer_setup_ops;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->dev.parent = &client->dev;
>  
>  	data = iio_priv(indio_dev);
> @@ -551,6 +543,11 @@ static int max30102_probe(struct i2c_client *client,
>  		return -ENODEV;
>  	}
>  
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &max30102_buffer_setup_ops);
> +	if (ret)
> +		return ret;
> +
>  	data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
>  	if (IS_ERR(data->regmap)) {
>  		dev_err(&client->dev, "regmap initialization failed\n");
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
> index bb899345f2bb..4ba3d5551570 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c

I'm not going to layout the details, but this one isn't unwinding in the same
order after this change.  There are devm_kzalloc calls between the devm_iio_device_alloc and
the new call.

> @@ -30,8 +30,8 @@
>   * Denis Ciocca <denis.ciocca@st.com>
>   */
>  #include <linux/module.h>
> -#include <linux/iio/kfifo_buf.h>
>  #include <linux/iio/iio.h>
> +#include <linux/iio/kfifo_buf.h>
>  #include <linux/iio/buffer.h>
>  #include <linux/regmap.h>
>  #include <linux/bitfield.h>
> @@ -713,20 +713,17 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
>  
>  int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
>  {
> -	struct iio_buffer *buffer;
> -	int i;
> +	int i, ret;
>  
>  	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
>  		if (!hw->iio_devs[i])
>  			continue;
>  
> -		buffer = devm_iio_kfifo_allocate(hw->dev);
> -		if (!buffer)
> -			return -ENOMEM;
> -
> -		iio_device_attach_buffer(hw->iio_devs[i], buffer);
> -		hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
> -		hw->iio_devs[i]->setup_ops = &st_lsm6dsx_buffer_ops;
> +		ret = iio_device_attach_kfifo_buffer(hw->iio_devs[i],
> +						     INDIO_BUFFER_SOFTWARE,
> +						     &st_lsm6dsx_buffer_ops);
> +		if (ret)
> +			return ret;
>  	}
>  
>  	return 0;
> diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c
> index 1eafd0b24e18..ea99705c3387 100644
> --- a/drivers/iio/light/acpi-als.c
> +++ b/drivers/iio/light/acpi-als.c
> @@ -166,6 +166,7 @@ static int acpi_als_add(struct acpi_device *device)
>  	struct acpi_als *als;
>  	struct iio_dev *indio_dev;
>  	struct iio_buffer *buffer;
> +	int ret;
>  
>  	indio_dev = devm_iio_device_alloc(&device->dev, sizeof(*als));
>  	if (!indio_dev)
> @@ -180,15 +181,13 @@ static int acpi_als_add(struct acpi_device *device)
>  	indio_dev->name = ACPI_ALS_DEVICE_NAME;
>  	indio_dev->dev.parent = &device->dev;
>  	indio_dev->info = &acpi_als_info;
> -	indio_dev->modes = INDIO_BUFFER_SOFTWARE;
>  	indio_dev->channels = acpi_als_channels;
>  	indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels);
>  
> -	buffer = devm_iio_kfifo_allocate(&device->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     NULL);
> +	if (ret)
> +		return ret;

This one is fine as next to the devm_iio_device_alloc anyway.

>  
>  	return devm_iio_device_register(&device->dev, indio_dev);
>  }
> diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
> index 52f86bc777dd..8acc319445b6 100644
> --- a/drivers/iio/light/apds9960.c
> +++ b/drivers/iio/light/apds9960.c
> @@ -987,7 +987,6 @@ static int apds9960_probe(struct i2c_client *client,
>  			  const struct i2c_device_id *id)
>  {
>  	struct apds9960_data *data;
> -	struct iio_buffer *buffer;
>  	struct iio_dev *indio_dev;
>  	int ret;
>  
> @@ -995,20 +994,18 @@ static int apds9960_probe(struct i2c_client *client,
>  	if (!indio_dev)
>  		return -ENOMEM;
>  
> -	buffer = devm_iio_kfifo_allocate(&client->dev);
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->info = &apds9960_info;
>  	indio_dev->name = APDS9960_DRV_NAME;
>  	indio_dev->channels = apds9960_channels;
>  	indio_dev->num_channels = ARRAY_SIZE(apds9960_channels);
>  	indio_dev->available_scan_masks = apds9960_scan_masks;
> -	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> -	indio_dev->setup_ops = &apds9960_buffer_setup_ops;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &apds9960_buffer_setup_ops);
> +	if (ret)
> +		return ret;

In this case we do have a managed call after this, but as there is nothing between
the devm_iio_device_alloc and iio_device_attach_kfifo_buffer I think we are fine.

>  
>  	data = iio_priv(indio_dev);
>  	i2c_set_clientdata(client, indio_dev);


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

* Re: [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper
  2020-04-01 12:59 [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
  2020-04-01 12:59 ` [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward Alexandru Ardelean
  2020-04-01 12:59 ` [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
@ 2020-04-05 10:46 ` Jonathan Cameron
  2020-04-06  8:12   ` Ardelean, Alexandru
  2 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2020-04-05 10:46 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-kernel, devel, knaack.h, lars, pmeerw,
	lorenzo.bianconi83

On Wed, 1 Apr 2020 15:59:34 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> This change adds the iio_device_attach_kfifo_buffer() helper/short-hand,
> which groups the simple routine of allocating a kfifo buffers via
> devm_iio_kfifo_allocate() and calling iio_device_attach_buffer().
> 
> The mode_flags parameter is required. The setup_ops parameter is optional.
> 
> This function will be a bit more useful when needing to define multiple
> buffers per IIO device.
> 
> One requirement [that is more a recommendation] for this helper, is to call
> it after 'indio_dev' has been populated.
> 
> Also, one consequence related to using this helper is that the resource
> management of the buffer will be tied to 'indio_dev->dev'. Previously it
> was open-coded, and each driver does it slightly differently. Most of them
> tied it to the parent device, some of them to 'indio_dev->dev'.
> This shouldn't be a problem, and may be a good idea when adding more
> buffers per-device.

I'm glad you highlighted this subtlety.  I'm not sure it's safe in all cases
because the result is that the managed cleanup for this will occur once we
get to the cleanup for devm_iio_device_alloc and we release the indio_dev->dev

That would put it 'after' any other devm calls that are still hung off the parent
device.

Now the question is whether that ever causes us problems... See next patch.
It potentially does.  I think we need to provide the dev separately even
if it feels a bit silly to do so.  Scope management is complex so I don't
really want to force people to mix and match between different devices
and so get it wrong by accident.

The other issue is that it's not readily apparent from the naming that
this function is registering stuff that is cleaned up automatically or
that it even allocates anything that might need that..

devm_iio_device_attach_new_kfifo_buffer maybe?

I'm sort of wondering if we should do what dma did and have

iiom_device_attach_new_kfifo_buffer to indicate it's managed in the
scope of the iio device?

What do people think?

However, see patch 2 before commenting.  Reality is I'm not sure forcing
managed calls to hang off iio_dev->dev is a good idea (at this stage given
where we are).

Thanks

Jonathan


> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---
>  drivers/iio/buffer/kfifo_buf.c | 37 ++++++++++++++++++++++++++++++++++
>  include/linux/iio/kfifo_buf.h  |  4 ++++
>  2 files changed, 41 insertions(+)
> 
> diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
> index 3150f8ab984b..05b7c5fc6f1d 100644
> --- a/drivers/iio/buffer/kfifo_buf.c
> +++ b/drivers/iio/buffer/kfifo_buf.c
> @@ -228,4 +228,41 @@ void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
>  }
>  EXPORT_SYMBOL(devm_iio_kfifo_free);
>  
> +/**
> + * iio_device_attach_kfifo_buffer - Allocate a kfifo buffer & attach it to an IIO device
> + * @indio_dev: The device the buffer should be attached to
> + * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE and/or
> + *		INDIO_BUFFER_TRIGGERED).
> + * @setup_ops: The setup_ops required to configure the HW part of the buffer (optional)
> + *
> + * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
> + * attaches it to the IIO device via iio_device_attach_buffer().
> + * This is meant to be a bit of a short-hand/helper function as many driver
> + * seem to do this.
> + */
> +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> +				   int mode_flags,
> +				   const struct iio_buffer_setup_ops *setup_ops)
> +{
> +	struct iio_buffer *buffer;
> +
> +	if (mode_flags)
> +		mode_flags &= kfifo_access_funcs.modes;
> +
> +	if (!mode_flags)
> +		return -EINVAL;
> +
> +	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	iio_device_attach_buffer(indio_dev, buffer);
> +
> +	indio_dev->modes |= mode_flags;
> +	indio_dev->setup_ops = setup_ops;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(iio_device_attach_kfifo_buffer);
> +
>  MODULE_LICENSE("GPL");
> diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
> index 764659e01b68..2363a931be14 100644
> --- a/include/linux/iio/kfifo_buf.h
> +++ b/include/linux/iio/kfifo_buf.h
> @@ -11,4 +11,8 @@ void iio_kfifo_free(struct iio_buffer *r);
>  struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev);
>  void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r);
>  
> +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> +				   int mode_flags,
> +				   const struct iio_buffer_setup_ops *setup_ops);
> +
>  #endif


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

* Re: [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper
  2020-04-01 12:59 ` [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
@ 2020-04-05 10:49   ` Jonathan Cameron
  2020-04-06  7:43     ` Ardelean, Alexandru
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2020-04-05 10:49 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-kernel, devel, knaack.h, lars, pmeerw,
	lorenzo.bianconi83

On Wed, 1 Apr 2020 15:59:36 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> This driver calls iio_kfifo_allocate() vs devm_iio_kfifo_allocate(). But
> the conversion is still simpler here, and cleans-up/reduces some error
> paths.
> 
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>

This mixes devm managed stuff an unmanaged.  Hence it fails the 'obviously correct'
test.  If you wanted to do this you'd first need to sort out the unmanaged
bits to be automatically unwound (regulators and clocks). Or potentially reorder
the driver so those happen after this allocation is done.

Thanks,

Jonathan

> ---
>  .../staging/iio/impedance-analyzer/ad5933.c   | 28 ++++---------------
>  1 file changed, 5 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
> index af0bcf95ee8a..7bde93c6dd74 100644
> --- a/drivers/staging/iio/impedance-analyzer/ad5933.c
> +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
> @@ -602,22 +602,6 @@ static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = {
>  	.postdisable = ad5933_ring_postdisable,
>  };
>  
> -static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
> -{
> -	struct iio_buffer *buffer;
> -
> -	buffer = iio_kfifo_allocate();
> -	if (!buffer)
> -		return -ENOMEM;
> -
> -	iio_device_attach_buffer(indio_dev, buffer);
> -
> -	/* Ring buffer functions - here trigger setup related */
> -	indio_dev->setup_ops = &ad5933_ring_setup_ops;
> -
> -	return 0;
> -}
> -
>  static void ad5933_work(struct work_struct *work)
>  {
>  	struct ad5933_state *st = container_of(work,
> @@ -738,26 +722,25 @@ static int ad5933_probe(struct i2c_client *client,
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->info = &ad5933_info;
>  	indio_dev->name = id->name;
> -	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> +	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->channels = ad5933_channels;
>  	indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
>  
> -	ret = ad5933_register_ring_funcs_and_init(indio_dev);
> +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> +					     &ad5933_ring_setup_ops);
>  	if (ret)
>  		goto error_disable_mclk;
>  
>  	ret = ad5933_setup(st);
>  	if (ret)
> -		goto error_unreg_ring;
> +		goto error_disable_mclk;
>  
>  	ret = iio_device_register(indio_dev);
>  	if (ret)
> -		goto error_unreg_ring;
> +		goto error_disable_mclk;
>  
>  	return 0;
>  
> -error_unreg_ring:
> -	iio_kfifo_free(indio_dev->buffer);
>  error_disable_mclk:
>  	clk_disable_unprepare(st->mclk);
>  error_disable_reg:
> @@ -772,7 +755,6 @@ static int ad5933_remove(struct i2c_client *client)
>  	struct ad5933_state *st = iio_priv(indio_dev);
>  
>  	iio_device_unregister(indio_dev);
> -	iio_kfifo_free(indio_dev->buffer);
>  	regulator_disable(st->reg);
>  	clk_disable_unprepare(st->mclk);
>  


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

* Re: [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper
  2020-04-05 10:49   ` Jonathan Cameron
@ 2020-04-06  7:43     ` Ardelean, Alexandru
  0 siblings, 0 replies; 9+ messages in thread
From: Ardelean, Alexandru @ 2020-04-06  7:43 UTC (permalink / raw)
  To: jic23
  Cc: pmeerw, devel, lorenzo.bianconi83, linux-kernel, linux-iio, lars,
	knaack.h

On Sun, 2020-04-05 at 11:49 +0100, Jonathan Cameron wrote:
> [External]
> 
> On Wed, 1 Apr 2020 15:59:36 +0300
> Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:
> 
> > This driver calls iio_kfifo_allocate() vs devm_iio_kfifo_allocate(). But
> > the conversion is still simpler here, and cleans-up/reduces some error
> > paths.
> > 
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> 
> This mixes devm managed stuff an unmanaged.  Hence it fails the 'obviously
> correct'
> test.  If you wanted to do this you'd first need to sort out the unmanaged
> bits to be automatically unwound (regulators and clocks). Or potentially
> reorder
> the driver so those happen after this allocation is done.
> 

Yeah.
I was a bit sloppy here.
I think tried a broader cleanup/rework would be a better idea here.


> Thanks,
> 
> Jonathan
> 
> > ---
> >  .../staging/iio/impedance-analyzer/ad5933.c   | 28 ++++---------------
> >  1 file changed, 5 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c
> > b/drivers/staging/iio/impedance-analyzer/ad5933.c
> > index af0bcf95ee8a..7bde93c6dd74 100644
> > --- a/drivers/staging/iio/impedance-analyzer/ad5933.c
> > +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
> > @@ -602,22 +602,6 @@ static const struct iio_buffer_setup_ops
> > ad5933_ring_setup_ops = {
> >  	.postdisable = ad5933_ring_postdisable,
> >  };
> >  
> > -static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
> > -{
> > -	struct iio_buffer *buffer;
> > -
> > -	buffer = iio_kfifo_allocate();
> > -	if (!buffer)
> > -		return -ENOMEM;
> > -
> > -	iio_device_attach_buffer(indio_dev, buffer);
> > -
> > -	/* Ring buffer functions - here trigger setup related */
> > -	indio_dev->setup_ops = &ad5933_ring_setup_ops;
> > -
> > -	return 0;
> > -}
> > -
> >  static void ad5933_work(struct work_struct *work)
> >  {
> >  	struct ad5933_state *st = container_of(work,
> > @@ -738,26 +722,25 @@ static int ad5933_probe(struct i2c_client *client,
> >  	indio_dev->dev.parent = &client->dev;
> >  	indio_dev->info = &ad5933_info;
> >  	indio_dev->name = id->name;
> > -	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> > +	indio_dev->modes = INDIO_DIRECT_MODE;
> >  	indio_dev->channels = ad5933_channels;
> >  	indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
> >  
> > -	ret = ad5933_register_ring_funcs_and_init(indio_dev);
> > +	ret = iio_device_attach_kfifo_buffer(indio_dev, INDIO_BUFFER_SOFTWARE,
> > +					     &ad5933_ring_setup_ops);
> >  	if (ret)
> >  		goto error_disable_mclk;
> >  
> >  	ret = ad5933_setup(st);
> >  	if (ret)
> > -		goto error_unreg_ring;
> > +		goto error_disable_mclk;
> >  
> >  	ret = iio_device_register(indio_dev);
> >  	if (ret)
> > -		goto error_unreg_ring;
> > +		goto error_disable_mclk;
> >  
> >  	return 0;
> >  
> > -error_unreg_ring:
> > -	iio_kfifo_free(indio_dev->buffer);
> >  error_disable_mclk:
> >  	clk_disable_unprepare(st->mclk);
> >  error_disable_reg:
> > @@ -772,7 +755,6 @@ static int ad5933_remove(struct i2c_client *client)
> >  	struct ad5933_state *st = iio_priv(indio_dev);
> >  
> >  	iio_device_unregister(indio_dev);
> > -	iio_kfifo_free(indio_dev->buffer);
> >  	regulator_disable(st->reg);
> >  	clk_disable_unprepare(st->mclk);
> >  

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

* Re: [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper
  2020-04-05 10:46 ` [PATCH 1/3] iio: kfifo: add " Jonathan Cameron
@ 2020-04-06  8:12   ` Ardelean, Alexandru
  2020-04-12 11:18     ` Jonathan Cameron
  0 siblings, 1 reply; 9+ messages in thread
From: Ardelean, Alexandru @ 2020-04-06  8:12 UTC (permalink / raw)
  To: jic23
  Cc: pmeerw, devel, lorenzo.bianconi83, linux-kernel, linux-iio, lars,
	knaack.h

On Sun, 2020-04-05 at 11:46 +0100, Jonathan Cameron wrote:
> [External]
> 
> On Wed, 1 Apr 2020 15:59:34 +0300
> Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:
> 
> > This change adds the iio_device_attach_kfifo_buffer() helper/short-hand,
> > which groups the simple routine of allocating a kfifo buffers via
> > devm_iio_kfifo_allocate() and calling iio_device_attach_buffer().
> > 
> > The mode_flags parameter is required. The setup_ops parameter is optional.
> > 
> > This function will be a bit more useful when needing to define multiple
> > buffers per IIO device.
> > 
> > One requirement [that is more a recommendation] for this helper, is to call
> > it after 'indio_dev' has been populated.
> > 
> > Also, one consequence related to using this helper is that the resource
> > management of the buffer will be tied to 'indio_dev->dev'. Previously it
> > was open-coded, and each driver does it slightly differently. Most of them
> > tied it to the parent device, some of them to 'indio_dev->dev'.
> > This shouldn't be a problem, and may be a good idea when adding more
> > buffers per-device.
> 
> I'm glad you highlighted this subtlety.  I'm not sure it's safe in all cases
> because the result is that the managed cleanup for this will occur once we
> get to the cleanup for devm_iio_device_alloc and we release the indio_dev->dev
> 
> That would put it 'after' any other devm calls that are still hung off the
> parent
> device.
> 
> Now the question is whether that ever causes us problems... See next patch.
> It potentially does.  I think we need to provide the dev separately even
> if it feels a bit silly to do so.  Scope management is complex so I don't
> really want to force people to mix and match between different devices
> and so get it wrong by accident.
> 
> The other issue is that it's not readily apparent from the naming that
> this function is registering stuff that is cleaned up automatically or
> that it even allocates anything that might need that..
> 
> devm_iio_device_attach_new_kfifo_buffer maybe?
> 
> I'm sort of wondering if we should do what dma did and have
> 
> iiom_device_attach_new_kfifo_buffer to indicate it's managed in the
> scope of the iio device?
> 
> What do people think?
> 
> However, see patch 2 before commenting.  Reality is I'm not sure forcing
> managed calls to hang off iio_dev->dev is a good idea (at this stage given
> where we are).

What I am really after with this patch is to hide away these:
     iio_kfifo_free(indio_dev->buffer);
     iio_buffer_set_attrs(indio_dev->buffer, xxxx_fifo_attributes); 
i.e. not have 'indio_dev->buffer' open-coded in drivers, and hide it in IIO core
somewhere.
Some ideas can go in parallel [like this one] to add support for multiple
buffers.

So, I will think of a better [less sloppy] V2 for this.

One intermediate alternative is to do 'iio_device_kfifo_free(indio_dev)', but
I'll still try to think of a better devm_ approach.
devm_iio_device_attach_new_kfifo_buffer() sounds a bit long but may work.
iiom_device_attach_new_kfifo_buffer() can also work.

What if we just default attaching to the parent device?

Would it work to also attach the parent device in devm_iio_device_alloc() by
default?
Or change 'iio_device_alloc()' to take a parent device as argument?
Which for devm_iio_device_alloc(dev,...) would implicitly mean that 'dev' is
'parent'?

These are just some thoughts.


> 
> Thanks
> 
> Jonathan
> 
> 
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > ---
> >  drivers/iio/buffer/kfifo_buf.c | 37 ++++++++++++++++++++++++++++++++++
> >  include/linux/iio/kfifo_buf.h  |  4 ++++
> >  2 files changed, 41 insertions(+)
> > 
> > diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
> > index 3150f8ab984b..05b7c5fc6f1d 100644
> > --- a/drivers/iio/buffer/kfifo_buf.c
> > +++ b/drivers/iio/buffer/kfifo_buf.c
> > @@ -228,4 +228,41 @@ void devm_iio_kfifo_free(struct device *dev, struct
> > iio_buffer *r)
> >  }
> >  EXPORT_SYMBOL(devm_iio_kfifo_free);
> >  
> > +/**
> > + * iio_device_attach_kfifo_buffer - Allocate a kfifo buffer & attach it to
> > an IIO device
> > + * @indio_dev: The device the buffer should be attached to
> > + * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE
> > and/or
> > + *		INDIO_BUFFER_TRIGGERED).
> > + * @setup_ops: The setup_ops required to configure the HW part of the
> > buffer (optional)
> > + *
> > + * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
> > + * attaches it to the IIO device via iio_device_attach_buffer().
> > + * This is meant to be a bit of a short-hand/helper function as many driver
> > + * seem to do this.
> > + */
> > +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> > +				   int mode_flags,
> > +				   const struct iio_buffer_setup_ops *setup_ops)
> > +{
> > +	struct iio_buffer *buffer;
> > +
> > +	if (mode_flags)
> > +		mode_flags &= kfifo_access_funcs.modes;
> > +
> > +	if (!mode_flags)
> > +		return -EINVAL;
> > +
> > +	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
> > +	if (!buffer)
> > +		return -ENOMEM;
> > +
> > +	iio_device_attach_buffer(indio_dev, buffer);
> > +
> > +	indio_dev->modes |= mode_flags;
> > +	indio_dev->setup_ops = setup_ops;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(iio_device_attach_kfifo_buffer);
> > +
> >  MODULE_LICENSE("GPL");
> > diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
> > index 764659e01b68..2363a931be14 100644
> > --- a/include/linux/iio/kfifo_buf.h
> > +++ b/include/linux/iio/kfifo_buf.h
> > @@ -11,4 +11,8 @@ void iio_kfifo_free(struct iio_buffer *r);
> >  struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev);
> >  void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r);
> >  
> > +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> > +				   int mode_flags,
> > +				   const struct iio_buffer_setup_ops
> > *setup_ops);
> > +
> >  #endif

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

* Re: [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper
  2020-04-06  8:12   ` Ardelean, Alexandru
@ 2020-04-12 11:18     ` Jonathan Cameron
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2020-04-12 11:18 UTC (permalink / raw)
  To: Ardelean, Alexandru
  Cc: pmeerw, devel, lorenzo.bianconi83, linux-kernel, linux-iio, lars,
	knaack.h

On Mon, 6 Apr 2020 08:12:42 +0000
"Ardelean, Alexandru" <alexandru.Ardelean@analog.com> wrote:

> On Sun, 2020-04-05 at 11:46 +0100, Jonathan Cameron wrote:
> > [External]
> > 
> > On Wed, 1 Apr 2020 15:59:34 +0300
> > Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:
> >   
> > > This change adds the iio_device_attach_kfifo_buffer() helper/short-hand,
> > > which groups the simple routine of allocating a kfifo buffers via
> > > devm_iio_kfifo_allocate() and calling iio_device_attach_buffer().
> > > 
> > > The mode_flags parameter is required. The setup_ops parameter is optional.
> > > 
> > > This function will be a bit more useful when needing to define multiple
> > > buffers per IIO device.
> > > 
> > > One requirement [that is more a recommendation] for this helper, is to call
> > > it after 'indio_dev' has been populated.
> > > 
> > > Also, one consequence related to using this helper is that the resource
> > > management of the buffer will be tied to 'indio_dev->dev'. Previously it
> > > was open-coded, and each driver does it slightly differently. Most of them
> > > tied it to the parent device, some of them to 'indio_dev->dev'.
> > > This shouldn't be a problem, and may be a good idea when adding more
> > > buffers per-device.  
> > 
> > I'm glad you highlighted this subtlety.  I'm not sure it's safe in all cases
> > because the result is that the managed cleanup for this will occur once we
> > get to the cleanup for devm_iio_device_alloc and we release the indio_dev->dev
> > 
> > That would put it 'after' any other devm calls that are still hung off the
> > parent
> > device.
> > 
> > Now the question is whether that ever causes us problems... See next patch.
> > It potentially does.  I think we need to provide the dev separately even
> > if it feels a bit silly to do so.  Scope management is complex so I don't
> > really want to force people to mix and match between different devices
> > and so get it wrong by accident.
> > 
> > The other issue is that it's not readily apparent from the naming that
> > this function is registering stuff that is cleaned up automatically or
> > that it even allocates anything that might need that..
> > 
> > devm_iio_device_attach_new_kfifo_buffer maybe?
> > 
> > I'm sort of wondering if we should do what dma did and have
> > 
> > iiom_device_attach_new_kfifo_buffer to indicate it's managed in the
> > scope of the iio device?
> > 
> > What do people think?
> > 
> > However, see patch 2 before commenting.  Reality is I'm not sure forcing
> > managed calls to hang off iio_dev->dev is a good idea (at this stage given
> > where we are).  
> 
> What I am really after with this patch is to hide away these:
>      iio_kfifo_free(indio_dev->buffer);
>      iio_buffer_set_attrs(indio_dev->buffer, xxxx_fifo_attributes); 
> i.e. not have 'indio_dev->buffer' open-coded in drivers, and hide it in IIO core
> somewhere.
> Some ideas can go in parallel [like this one] to add support for multiple
> buffers.
> 
> So, I will think of a better [less sloppy] V2 for this.
> 
> One intermediate alternative is to do 'iio_device_kfifo_free(indio_dev)', but
> I'll still try to think of a better devm_ approach.
> devm_iio_device_attach_new_kfifo_buffer() sounds a bit long but may work.
> iiom_device_attach_new_kfifo_buffer() can also work.
> 
> What if we just default attaching to the parent device?

That would work and be consistent with the vast majority of current cases.

> 
> Would it work to also attach the parent device in devm_iio_device_alloc() by
> default?

That would need a thorough audit to check nothing crazy is done by
a driver with an odd structure.  Such a driver would (I think) be
buggy though as the child lifetime should be dependent on the parent
and not some other device.

> Or change 'iio_device_alloc()' to take a parent device as argument?

I think there are only a couple of users, so that would work.

> Which for devm_iio_device_alloc(dev,...) would implicitly mean that 'dev' is
> 'parent'?

I think that's a fair assumption (though needs a sanity check)

> 
> These are just some thoughts.
> 
> 
> > 
> > Thanks
> > 
> > Jonathan
> > 
> >   
> > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > > ---
> > >  drivers/iio/buffer/kfifo_buf.c | 37 ++++++++++++++++++++++++++++++++++
> > >  include/linux/iio/kfifo_buf.h  |  4 ++++
> > >  2 files changed, 41 insertions(+)
> > > 
> > > diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
> > > index 3150f8ab984b..05b7c5fc6f1d 100644
> > > --- a/drivers/iio/buffer/kfifo_buf.c
> > > +++ b/drivers/iio/buffer/kfifo_buf.c
> > > @@ -228,4 +228,41 @@ void devm_iio_kfifo_free(struct device *dev, struct
> > > iio_buffer *r)
> > >  }
> > >  EXPORT_SYMBOL(devm_iio_kfifo_free);
> > >  
> > > +/**
> > > + * iio_device_attach_kfifo_buffer - Allocate a kfifo buffer & attach it to
> > > an IIO device
> > > + * @indio_dev: The device the buffer should be attached to
> > > + * @mode_flags: The mode flags for this buffer (INDIO_BUFFER_SOFTWARE
> > > and/or
> > > + *		INDIO_BUFFER_TRIGGERED).
> > > + * @setup_ops: The setup_ops required to configure the HW part of the
> > > buffer (optional)
> > > + *
> > > + * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
> > > + * attaches it to the IIO device via iio_device_attach_buffer().
> > > + * This is meant to be a bit of a short-hand/helper function as many driver
> > > + * seem to do this.
> > > + */
> > > +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> > > +				   int mode_flags,
> > > +				   const struct iio_buffer_setup_ops *setup_ops)
> > > +{
> > > +	struct iio_buffer *buffer;
> > > +
> > > +	if (mode_flags)
> > > +		mode_flags &= kfifo_access_funcs.modes;
> > > +
> > > +	if (!mode_flags)
> > > +		return -EINVAL;
> > > +
> > > +	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
> > > +	if (!buffer)
> > > +		return -ENOMEM;
> > > +
> > > +	iio_device_attach_buffer(indio_dev, buffer);
> > > +
> > > +	indio_dev->modes |= mode_flags;
> > > +	indio_dev->setup_ops = setup_ops;
> > > +
> > > +	return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(iio_device_attach_kfifo_buffer);
> > > +
> > >  MODULE_LICENSE("GPL");
> > > diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h
> > > index 764659e01b68..2363a931be14 100644
> > > --- a/include/linux/iio/kfifo_buf.h
> > > +++ b/include/linux/iio/kfifo_buf.h
> > > @@ -11,4 +11,8 @@ void iio_kfifo_free(struct iio_buffer *r);
> > >  struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev);
> > >  void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r);
> > >  
> > > +int iio_device_attach_kfifo_buffer(struct iio_dev *indio_dev,
> > > +				   int mode_flags,
> > > +				   const struct iio_buffer_setup_ops
> > > *setup_ops);
> > > +
> > >  #endif  


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

end of thread, other threads:[~2020-04-12 11:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-01 12:59 [PATCH 1/3] iio: kfifo: add iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
2020-04-01 12:59 ` [PATCH 2/3] iio: make use of iio_device_attach_kfifo_buffer() where straightforward Alexandru Ardelean
2020-04-05 10:44   ` Jonathan Cameron
2020-04-01 12:59 ` [PATCH 3/3] staging: iio: ad5933: use iio_device_attach_kfifo_buffer() helper Alexandru Ardelean
2020-04-05 10:49   ` Jonathan Cameron
2020-04-06  7:43     ` Ardelean, Alexandru
2020-04-05 10:46 ` [PATCH 1/3] iio: kfifo: add " Jonathan Cameron
2020-04-06  8:12   ` Ardelean, Alexandru
2020-04-12 11:18     ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).