2021-01-22 16:49:48

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 00/12][RESEND] iio: core,buffer: add support for multiple IIO buffers per IIO device

Continuing from:
https://lore.kernel.org/linux-iio/[email protected]/

Changelog v1 -> v2:
* 'iio: buffer: rework buffer & scan_elements dir creation'
add more doc-strings detailing the reasoning for this change
* 'iio: buffer: re-route scan_elements via it's kobj_type'
move list_del() before the kfree()'s in the list destruction
* 'iio: buffer: introduce support for attaching more IIO buffers'
- changed to 'cnt' variable vs re-using the 'i' for unwinding in
iio_buffer_alloc_sysfs_and_mask()
- removed kfree(old) in iio_device_attach_buffer()
- made iio_device_attach_buffer() an int return; this means that some
follow up patches are needed to make this return value be used;
* 'iio: buffer: add ioctl() to support opening extra buffers for IIO device'
- tested ioctl() with a simple C program; attached to comment;
- changed 'i' variable usage to 'sz' for alloc
- changed logic for buffer0; returning FD 0; userspace should know
that the IIO_BUFFER_GET_FD_IOCTL call returns 0 for buffer0;
this is because I can't find a way to determine the FD of the
ioctl() in the kernel; duplicating an ioctl() for buffer0 is also bad;

Alexandru Ardelean (12):
iio: core: register chardev only if needed
iio: buffer: add back-ref from iio_buffer to iio_dev
iio: buffer: rework buffer & scan_elements dir creation
iio: buffer: add index to the first IIO buffer dir and symlink it back
iio: core: split __iio_device_attr_init() to init only the attr object
iio: buffer: re-route scan_elements via it's kobj_type
iio: buffer: re-route core buffer attributes via it's new kobj_type
iio: buffer: add helper to get the IIO device to which a buffer
belongs
iio: re-route all buffer attributes through new buffer kobj_type
iio: core: wrap iio device & buffer into struct for character devices
iio: buffer: introduce support for attaching more IIO buffers
iio: buffer: add ioctl() to support opening extra buffers for IIO
device

drivers/iio/accel/adxl372.c | 36 +-
drivers/iio/accel/bmc150-accel-core.c | 34 +-
drivers/iio/adc/at91-sama5d2_adc.c | 30 +-
.../buffer/industrialio-buffer-dmaengine.c | 13 +-
.../cros_ec_sensors/cros_ec_sensors_core.c | 30 +-
.../common/hid-sensors/hid-sensor-trigger.c | 32 +-
drivers/iio/iio_core.h | 11 +
drivers/iio/industrialio-buffer.c | 647 ++++++++++++++----
drivers/iio/industrialio-core.c | 117 ++--
include/linux/iio/buffer.h | 6 +-
include/linux/iio/buffer_impl.h | 25 +-
include/linux/iio/iio-opaque.h | 6 +
include/linux/iio/iio.h | 2 +-
include/linux/iio/sysfs.h | 50 ++
include/uapi/linux/iio/buffer.h | 10 +
15 files changed, 790 insertions(+), 259 deletions(-)
create mode 100644 include/uapi/linux/iio/buffer.h

--
2.17.1


2021-01-22 17:10:25

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 08/12][RESEND] iio: buffer: add helper to get the IIO device to which a buffer belongs

This is useful for drivers that may have a reference to an IIO buffer, to
be able to get a reference back to the IIO device.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-buffer.c | 14 ++++++++++++++
include/linux/iio/buffer.h | 2 ++
2 files changed, 16 insertions(+)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 8470921cf2fa..a2dd30567072 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1778,6 +1778,20 @@ void iio_buffer_put(struct iio_buffer *buffer)
}
EXPORT_SYMBOL_GPL(iio_buffer_put);

+/**
+ * iio_buffer_get_iio_dev - Get the IIO device to which this buffer belongs to
+ * @buffer: The buffer for which to retrieve the IIO device
+ *
+ * This function retrieves the IIO device to which this IIO buffer is attached
+ * to. Given that an IIO device may have multiple IIO buffers, it's useful
+ * for some drivers to obtain a reference back to the IIO device.
+ */
+struct iio_dev *iio_buffer_get_iio_dev(struct iio_buffer *buffer)
+{
+ return buffer->indio_dev;
+}
+EXPORT_SYMBOL_GPL(iio_buffer_get_iio_dev);
+
/**
* iio_device_attach_buffer - Attach a buffer to a IIO device
* @indio_dev: The device the buffer should be attached to
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index 8febc23f5f26..b27d8c81f32c 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -11,6 +11,8 @@

struct iio_buffer;

+struct iio_dev *iio_buffer_get_iio_dev(struct iio_buffer *buffer);
+
int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data);

/**
--
2.17.1

2021-01-22 17:10:45

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 11/12][RESEND] iio: buffer: introduce support for attaching more IIO buffers

With this change, calling iio_device_attach_buffer() will actually attach
more buffers.
Right now this doesn't do any validation of whether a buffer is attached
twice; maybe that can be added later (if needed). Attaching a buffer more
than once should yield noticeably bad results.

The first buffer is the legacy buffer, so a reference is kept to it.

At this point, accessing the data for the extra buffers (that are added
after the first one) isn't possible yet.

The iio_device_attach_buffer() is also changed to return an error code,
which for now is -ENOMEM if the array could not be realloc-ed for more
buffers.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-buffer.c | 67 ++++++++++++++++++++++++-------
include/linux/iio/buffer.h | 4 +-
include/linux/iio/buffer_impl.h | 3 ++
include/linux/iio/iio-opaque.h | 4 ++
4 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 62cb90385246..2f429616e998 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1561,9 +1561,10 @@ static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
*/
int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
{
+ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_buffer *buffer = indio_dev->buffer;
const struct iio_chan_spec *channels;
- int i, ret;
+ int i, cnt, ret;

channels = indio_dev->channels;
if (channels) {
@@ -1577,15 +1578,18 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
if (!buffer)
return 0;

- ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, 0);
- if (ret)
- return ret;
+ for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
+ buffer = iio_dev_opaque->attached_buffers[i];
+ ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, i);
+ if (ret)
+ goto error_unwind_sysfs_and_mask;
+ }

ret = sysfs_create_link(&indio_dev->dev.kobj,
&indio_dev->buffer->buffer_dir,
"buffer");
if (ret)
- goto error_free_sysfs_and_mask;
+ goto error_unwind_sysfs_and_mask;

ret = sysfs_create_link(&indio_dev->dev.kobj,
&indio_dev->buffer->scan_el_dir,
@@ -1597,8 +1601,14 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)

error_remove_buffer_dir_link:
sysfs_remove_link(&indio_dev->dev.kobj, "buffer");
-error_free_sysfs_and_mask:
- __iio_buffer_free_sysfs_and_mask(buffer);
+ cnt = iio_dev_opaque->attached_buffers_cnt - 1;
+error_unwind_sysfs_and_mask:
+ for (; cnt >= 0; cnt--) {
+ buffer = iio_dev_opaque->attached_buffers[cnt];
+ __iio_buffer_free_sysfs_and_mask(buffer);
+ }
+ kfree(iio_dev_opaque->attached_buffers);
+ iio_dev_opaque->attached_buffers = NULL;
return ret;
}

@@ -1610,7 +1620,9 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
*/
void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
{
+ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_buffer *buffer = indio_dev->buffer;
+ int i;

if (!buffer)
return;
@@ -1618,7 +1630,13 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
sysfs_remove_link(&indio_dev->dev.kobj, "scan_elements");
sysfs_remove_link(&indio_dev->dev.kobj, "buffer");

- __iio_buffer_free_sysfs_and_mask(buffer);
+ for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) {
+ buffer = iio_dev_opaque->attached_buffers[i];
+ __iio_buffer_free_sysfs_and_mask(buffer);
+ }
+
+ kfree(iio_dev_opaque->attached_buffers);
+ iio_dev_opaque->attached_buffers = NULL;
}

/**
@@ -1750,15 +1768,36 @@ EXPORT_SYMBOL_GPL(iio_buffer_get_iio_dev);
* @indio_dev: The device the buffer should be attached to
* @buffer: The buffer to attach to the device
*
+ * Return 0 if buffer attached, or negative if error occured.
+ *
* This function attaches a buffer to a IIO device. The buffer stays attached to
- * the device until the device is freed. The function should only be called at
- * most once per device.
+ * the device until the device is freed. For legacy reasons, the first attached
+ * buffer will also be assigned to 'indio_dev->buffer'.
*/
-void iio_device_attach_buffer(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+int iio_device_attach_buffer(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer)
{
- indio_dev->buffer = iio_buffer_get(buffer);
+ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+ struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers;
+ unsigned int cnt = iio_dev_opaque->attached_buffers_cnt;
+
+ cnt++;
+
+ new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;

- indio_dev->buffer->indio_dev = indio_dev;
+ iio_dev_opaque->attached_buffers = new;
+
+ /* first buffer is legacy; attach it to the IIO device directly */
+ if (!indio_dev->buffer)
+ indio_dev->buffer = iio_buffer_get(buffer);
+
+ buffer->indio_dev = indio_dev;
+
+ iio_dev_opaque->attached_buffers[cnt - 1] = buffer;
+ iio_dev_opaque->attached_buffers_cnt = cnt;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index b27d8c81f32c..5532eddb7808 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -43,7 +43,7 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
const unsigned long *mask);

-void iio_device_attach_buffer(struct iio_dev *indio_dev,
- struct iio_buffer *buffer);
+int iio_device_attach_buffer(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer);

#endif /* _IIO_BUFFER_GENERIC_H_ */
diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h
index 77e169e51434..e25d26a7f601 100644
--- a/include/linux/iio/buffer_impl.h
+++ b/include/linux/iio/buffer_impl.h
@@ -124,6 +124,9 @@ struct iio_buffer {
/* @demux_bounce: Buffer for doing gather from incoming scan. */
void *demux_bounce;

+ /* @attached_entry: Entry in the devices list of buffers attached by the driver. */
+ struct list_head attached_entry;
+
/* @buffer_list: Entry in the devices list of current buffers. */
struct list_head buffer_list;

diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
index 07c5a8e52ca8..1db0ea09520e 100644
--- a/include/linux/iio/iio-opaque.h
+++ b/include/linux/iio/iio-opaque.h
@@ -7,6 +7,8 @@
* struct iio_dev_opaque - industrial I/O device opaque information
* @indio_dev: public industrial I/O device information
* @event_interface: event chrdevs associated with interrupt lines
+ * @attached_buffers: array of buffers statically attached by the driver
+ * @attached_buffers_cnt: number of buffers in the array of statically attached buffers
* @buffer_list: list of all buffers currently attached
* @channel_attr_list: keep track of automatically created channel
* attributes
@@ -20,6 +22,8 @@
struct iio_dev_opaque {
struct iio_dev indio_dev;
struct iio_event_interface *event_interface;
+ struct iio_buffer **attached_buffers;
+ unsigned int attached_buffers_cnt;
struct list_head buffer_list;
struct list_head channel_attr_list;
struct attribute_group chan_attr_group;
--
2.17.1

2021-01-22 17:11:02

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 09/12][RESEND] iio: re-route all buffer attributes through new buffer kobj_type

Now that the iio_buffer_set_attrs() has been removed, we can be sure that
no accidents can happen with drivers that try to provide extra buffer
attributes that expand to iio_dev objects.

So, we can convert all remaining buffer attributes to expand to iio_buffer
objects.
These will look a bit weird at first, as most of them will just pass back
their reference to the IIO device.
But this can also allow for newer (maybe more interesting) uses.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/accel/adxl372.c | 36 ++++-----
drivers/iio/accel/bmc150-accel-core.c | 34 ++++-----
drivers/iio/adc/at91-sama5d2_adc.c | 30 ++++----
.../buffer/industrialio-buffer-dmaengine.c | 13 ++--
.../cros_ec_sensors/cros_ec_sensors_core.c | 30 ++++----
.../common/hid-sensors/hid-sensor-trigger.c | 32 ++++----
drivers/iio/industrialio-buffer.c | 73 +++----------------
include/linux/iio/sysfs.h | 50 +++++++++++++
8 files changed, 148 insertions(+), 150 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 8ba1453b8dbf..a90aaa518816 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -978,39 +978,39 @@ static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
return len;
}

-static ssize_t adxl372_get_fifo_enabled(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t adxl372_get_fifo_enabled(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
+ char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct adxl372_state *st = iio_priv(indio_dev);

return sprintf(buf, "%d\n", st->fifo_mode);
}

-static ssize_t adxl372_get_fifo_watermark(struct device *dev,
- struct device_attribute *attr,
+static ssize_t adxl372_get_fifo_watermark(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct adxl372_state *st = iio_priv(indio_dev);

return sprintf(buf, "%d\n", st->watermark);
}

-static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
-static IIO_CONST_ATTR(hwfifo_watermark_max,
- __stringify(ADXL372_FIFO_SIZE));
-static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
- adxl372_get_fifo_watermark, NULL, 0);
-static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
- adxl372_get_fifo_enabled, NULL, 0);
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_min, "1");
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_max,
+ __stringify(ADXL372_FIFO_SIZE));
+static IIO_BUF_ATTR(hwfifo_watermark, 0444,
+ adxl372_get_fifo_watermark, NULL);
+static IIO_BUF_ATTR(hwfifo_enabled, 0444,
+ adxl372_get_fifo_enabled, NULL);

static const struct attribute *adxl372_fifo_attributes[] = {
- &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
- &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
- &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_min.buf_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_max.buf_attr.attr,
+ &iio_buf_attr_hwfifo_watermark.attr,
+ &iio_buf_attr_hwfifo_enabled.attr,
NULL,
};

diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 7e425ebcd7ea..87b1ad523106 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -867,11 +867,11 @@ static int bmc150_accel_validate_trigger(struct iio_dev *indio_dev,
return -EINVAL;
}

-static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
- struct device_attribute *attr,
+static ssize_t bmc150_accel_get_fifo_watermark(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct bmc150_accel_data *data = iio_priv(indio_dev);
int wm;

@@ -882,11 +882,11 @@ static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
return sprintf(buf, "%d\n", wm);
}

-static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
- struct device_attribute *attr,
+static ssize_t bmc150_accel_get_fifo_state(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct bmc150_accel_data *data = iio_priv(indio_dev);
bool state;

@@ -911,19 +911,19 @@ static const struct iio_chan_spec_ext_info bmc150_accel_ext_info[] = {
{ }
};

-static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
-static IIO_CONST_ATTR(hwfifo_watermark_max,
- __stringify(BMC150_ACCEL_FIFO_LENGTH));
-static IIO_DEVICE_ATTR(hwfifo_enabled, S_IRUGO,
- bmc150_accel_get_fifo_state, NULL, 0);
-static IIO_DEVICE_ATTR(hwfifo_watermark, S_IRUGO,
- bmc150_accel_get_fifo_watermark, NULL, 0);
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_min, "1");
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_max,
+ __stringify(BMC150_ACCEL_FIFO_LENGTH));
+static IIO_BUF_ATTR(hwfifo_enabled, S_IRUGO,
+ bmc150_accel_get_fifo_state, NULL);
+static IIO_BUF_ATTR(hwfifo_watermark, S_IRUGO,
+ bmc150_accel_get_fifo_watermark, NULL);

static const struct attribute *bmc150_accel_fifo_attributes[] = {
- &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
- &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
- &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_min.buf_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_max.buf_attr.attr,
+ &iio_buf_attr_hwfifo_watermark.attr,
+ &iio_buf_attr_hwfifo_enabled.attr,
NULL,
};

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index a7826f097b95..a573f0d5d0d8 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1610,31 +1610,29 @@ static void at91_adc_hw_init(struct iio_dev *indio_dev)
at91_adc_config_emr(st);
}

-static ssize_t at91_adc_get_fifo_state(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t at91_adc_get_fifo_state(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct at91_adc_state *st = iio_priv(indio_dev);

return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan);
}

-static ssize_t at91_adc_get_watermark(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t at91_adc_get_watermark(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct at91_adc_state *st = iio_priv(indio_dev);

return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark);
}

-static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
- at91_adc_get_fifo_state, NULL, 0);
-static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
- at91_adc_get_watermark, NULL, 0);
+static IIO_BUF_ATTR(hwfifo_enabled, 0444, at91_adc_get_fifo_state, NULL);
+static IIO_BUF_ATTR(hwfifo_watermark, 0444, at91_adc_get_watermark, NULL);

-static IIO_CONST_ATTR(hwfifo_watermark_min, "2");
-static IIO_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR);
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_min, "2");
+static IIO_BUF_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR);

static IIO_CONST_ATTR(oversampling_ratio_available,
__stringify(AT91_OSR_1SAMPLES) " "
@@ -1651,10 +1649,10 @@ static const struct attribute_group at91_adc_attribute_group = {
};

static const struct attribute *at91_adc_fifo_attributes[] = {
- &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
- &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
- &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_min.buf_attr.attr,
+ &iio_buf_const_attr_hwfifo_watermark_max.buf_attr.attr,
+ &iio_buf_attr_hwfifo_watermark.attr,
+ &iio_buf_attr_hwfifo_enabled.attr,
NULL,
};

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index b0cb9a35f5cd..2cd5fd3fe191 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -129,21 +129,20 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = {
.abort = iio_dmaengine_buffer_abort,
};

-static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t iio_dmaengine_buffer_get_length_align(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct dmaengine_buffer *dmaengine_buffer =
- iio_buffer_to_dmaengine_buffer(indio_dev->buffer);
+ iio_buffer_to_dmaengine_buffer(buffer);

return sprintf(buf, "%zu\n", dmaengine_buffer->align);
}

-static IIO_DEVICE_ATTR(length_align_bytes, 0444,
- iio_dmaengine_buffer_get_length_align, NULL, 0);
+static IIO_BUF_ATTR(length_align_bytes, 0444,
+ iio_dmaengine_buffer_get_length_align, NULL);

static const struct attribute *iio_dmaengine_buffer_attrs[] = {
- &iio_dev_attr_length_align_bytes.dev_attr.attr,
+ &iio_buf_attr_length_align_bytes.attr,
NULL,
};

diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
index 4e7b3bc187c9..99f2f9146fab 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -116,11 +116,11 @@ static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st,
return ret;
}

-static ssize_t cros_ec_sensor_set_report_latency(struct device *dev,
- struct device_attribute *attr,
+static ssize_t cros_ec_sensor_set_report_latency(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
int integer, fract, ret;
int latency;
@@ -138,11 +138,11 @@ static ssize_t cros_ec_sensor_set_report_latency(struct device *dev,
return len;
}

-static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
- struct device_attribute *attr,
+static ssize_t cros_ec_sensor_get_report_latency(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
int latency, ret;

@@ -161,25 +161,25 @@ static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
(latency % 1000) * 1000);
}

-static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
- cros_ec_sensor_get_report_latency,
- cros_ec_sensor_set_report_latency, 0);
+static IIO_BUF_ATTR(hwfifo_timeout, 0644,
+ cros_ec_sensor_get_report_latency,
+ cros_ec_sensor_set_report_latency);

-static ssize_t hwfifo_watermark_max_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t hwfifo_watermark_max_show(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);

return sprintf(buf, "%d\n", st->fifo_max_event_count);
}

-static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
+static IIO_BUF_ATTR(hwfifo_watermark_max, 0444, hwfifo_watermark_max_show, NULL);

static const struct attribute *cros_ec_sensor_fifo_attributes[] = {
- &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
+ &iio_buf_attr_hwfifo_timeout.attr,
+ &iio_buf_attr_hwfifo_watermark_max.attr,
NULL,
};

diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 064c32bec9c7..c04dca7a457b 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -19,11 +19,11 @@
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"

-static ssize_t _hid_sensor_set_report_latency(struct device *dev,
- struct device_attribute *attr,
+static ssize_t _hid_sensor_set_report_latency(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
int integer, fract, ret;
int latency;
@@ -42,11 +42,11 @@ static ssize_t _hid_sensor_set_report_latency(struct device *dev,
return len;
}

-static ssize_t _hid_sensor_get_report_latency(struct device *dev,
- struct device_attribute *attr,
+static ssize_t _hid_sensor_get_report_latency(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
int latency;

@@ -57,11 +57,11 @@ static ssize_t _hid_sensor_get_report_latency(struct device *dev,
return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000);
}

-static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
- struct device_attribute *attr,
+static ssize_t _hid_sensor_get_fifo_state(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_iio_dev(buffer);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
int latency;

@@ -72,15 +72,15 @@ static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
return sprintf(buf, "%d\n", !!latency);
}

-static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
- _hid_sensor_get_report_latency,
- _hid_sensor_set_report_latency, 0);
-static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
- _hid_sensor_get_fifo_state, NULL, 0);
+static IIO_BUF_ATTR(hwfifo_timeout, 0644,
+ _hid_sensor_get_report_latency,
+ _hid_sensor_set_report_latency);
+static IIO_BUF_ATTR(hwfifo_enabled, 0444,
+ _hid_sensor_get_fifo_state, NULL);

static const struct attribute *hid_sensor_fifo_attributes[] = {
- &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
- &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ &iio_buf_attr_hwfifo_timeout.attr,
+ &iio_buf_attr_hwfifo_enabled.attr,
NULL,
};

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index a2dd30567072..887c71272e9c 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -26,31 +26,19 @@
#include <linux/iio/buffer.h>
#include <linux/iio/buffer_impl.h>

-/**
- * struct iio_buf_attr - iio buffer specific attribute
- * @attr: underlying attribute
- * @address: associated register address
- * @l: list head for maintaining list of dynamically created attrs
- * @c: specification for the underlying channel
- * @show: sysfs show hook for this attribute
- * @store: sysfs store hook for this attribute
- */
-struct iio_buf_attr {
- struct attribute attr;
- u64 address;
- struct list_head l;
- struct iio_chan_spec const *c;
- ssize_t (*show)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
- char *buf);
- ssize_t (*store)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
- const char *buf, size_t count);
-};
-
static const char * const iio_endian_prefix[] = {
[IIO_BE] = "be",
[IIO_LE] = "le",
};

+ssize_t iio_read_buf_const_attr(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", to_iio_buf_const_attr(attr)->string);
+}
+EXPORT_SYMBOL(iio_read_buf_const_attr);
+
static bool iio_buffer_is_active(struct iio_buffer *buf)
{
return !list_empty(&buf->buffer_list);
@@ -1300,10 +1288,6 @@ static ssize_t iio_dma_show_data_available(struct iio_buffer *buffer,
return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
}

-#define IIO_BUF_ATTR(_name, _mode, _show, _store) \
- struct iio_buf_attr iio_buf_attr_##_name = \
- __ATTR(_name, _mode, _show, _store)
-
static IIO_BUF_ATTR(length, S_IRUGO | S_IWUSR,
iio_buffer_read_length, iio_buffer_write_length);
static struct iio_buf_attr buf_attr_length_ro = __ATTR(length,
@@ -1324,39 +1308,14 @@ static struct attribute *iio_buffer_attrs[] = {
&iio_buf_attr_data_available.attr,
};

-static bool iio_buffer_attr_is_core(struct attribute *attr)
-{
- struct attribute *a;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(iio_buffer_attrs); i++) {
- a = iio_buffer_attrs[i];
- if (!strcmp(attr->name, a->name))
- return true;
- }
-
- return false;
-}
-
-#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
-#define to_iio_buf_attr(_attr) container_of(_attr, struct iio_buf_attr, attr)
-
static ssize_t iio_buffer_dir_attr_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
{
struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, buffer_dir);
- struct device_attribute *dattr;
- struct iio_buf_attr *battr;
-
- if (iio_buffer_attr_is_core(attr)) {
- battr = to_iio_buf_attr(attr);
- return battr->show(buffer, battr, buf);
- }
-
- dattr = to_dev_attr(attr);
+ struct iio_buf_attr *battr = to_iio_buf_attr(attr);

- return dattr->show(&buffer->indio_dev->dev, dattr, buf);
+ return battr->show(buffer, battr, buf);
}

static ssize_t iio_buffer_dir_attr_store(struct kobject *kobj,
@@ -1365,17 +1324,9 @@ static ssize_t iio_buffer_dir_attr_store(struct kobject *kobj,
size_t len)
{
struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, buffer_dir);
- struct device_attribute *dattr;
- struct iio_buf_attr *battr;
-
- if (iio_buffer_attr_is_core(attr)) {
- battr = to_iio_buf_attr(attr);
- return battr->store(buffer, battr, buf, len);
- }
-
- dattr = to_dev_attr(attr);
+ struct iio_buf_attr *battr = to_iio_buf_attr(attr);

- return dattr->store(&buffer->indio_dev->dev, dattr, buf, len);
+ return battr->store(buffer, battr, buf, len);
}

static const struct sysfs_ops iio_buffer_dir_sysfs_ops = {
diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h
index b532c875bc24..d25b47971c09 100644
--- a/include/linux/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
@@ -9,6 +9,7 @@
#ifndef _INDUSTRIAL_IO_SYSFS_H_
#define _INDUSTRIAL_IO_SYSFS_H_

+struct iio_buffer;
struct iio_chan_spec;

/**
@@ -28,6 +29,55 @@ struct iio_dev_attr {
#define to_iio_dev_attr(_dev_attr) \
container_of(_dev_attr, struct iio_dev_attr, dev_attr)

+/**
+ * struct iio_buf_attr - iio buffer specific attribute
+ * @attr: underlying attribute
+ * @address: associated register address
+ * @l: list head for maintaining list of dynamically created attrs
+ * @c: specification for the underlying channel
+ * @show: sysfs show hook for this attribute
+ * @store: sysfs store hook for this attribute
+ */
+struct iio_buf_attr {
+ struct attribute attr;
+ u64 address;
+ struct list_head l;
+ struct iio_chan_spec const *c;
+ ssize_t (*show)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
+ char *buf);
+ ssize_t (*store)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
+ const char *buf, size_t count);
+};
+
+/**
+ * struct iio_buf_const_attr - constant buffer specific attribute
+ * often used for things constant parameters of buffers
+ * @string: attribute string
+ * @buf_attr: underlying buffer attribute
+ */
+struct iio_buf_const_attr {
+ const char *string;
+ struct iio_buf_attr buf_attr;
+};
+
+#define to_iio_buf_attr(_attr) container_of(_attr, struct iio_buf_attr, attr)
+
+#define IIO_BUF_ATTR(_name, _mode, _show, _store) \
+ struct iio_buf_attr iio_buf_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+#define IIO_BUF_CONST_ATTR(_name, _string) \
+ struct iio_buf_const_attr iio_buf_const_attr_##_name \
+ = { .string = _string, \
+ .buf_attr = __ATTR(_name, 0444, iio_read_buf_const_attr, NULL)}
+
+#define to_iio_buf_const_attr(_buf_attr) \
+ container_of(_buf_attr, struct iio_buf_const_attr, buf_attr)
+
+ssize_t iio_read_buf_const_attr(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
+ char *len);
+
ssize_t iio_read_const_attr(struct device *dev,
struct device_attribute *attr,
char *len);
--
2.17.1

2021-01-22 17:11:55

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 10/12][RESEND] iio: core: wrap iio device & buffer into struct for character devices

In order to keep backwards compatibility with the current chardev
mechanism, and in order to add support for multiple buffers per IIO device,
we need to pass both the IIO device & IIO buffer to the chardev.

This is particularly needed for the iio_buffer_read_outer() function, where
we need to pass another buffer object than 'indio_dev->buffer'.

Since we'll also open some chardevs via anon inodes, we can pass extra
buffers in that function by assigning another object to the
iio_dev_buffer_pair object.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/iio_core.h | 6 ++++++
drivers/iio/industrialio-buffer.c | 10 ++++++----
drivers/iio/industrialio-core.c | 18 ++++++++++++++++--
3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 43d44ec92781..ad6716fe1a93 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -12,11 +12,17 @@
#include <linux/kernel.h>
#include <linux/device.h>

+struct iio_buffer;
struct iio_chan_spec;
struct iio_dev;

extern struct device_type iio_device_type;

+struct iio_dev_buffer_pair {
+ struct iio_dev *indio_dev;
+ struct iio_buffer *buffer;
+};
+
#define IIO_IOCTL_UNHANDLED 1
struct iio_ioctl_handler {
struct list_head entry;
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 887c71272e9c..62cb90385246 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -112,8 +112,9 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
size_t n, loff_t *f_ps)
{
- struct iio_dev *indio_dev = filp->private_data;
- struct iio_buffer *rb = indio_dev->buffer;
+ struct iio_dev_buffer_pair *ib = filp->private_data;
+ struct iio_buffer *rb = ib->buffer;
+ struct iio_dev *indio_dev = ib->indio_dev;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
size_t datum_size;
size_t to_wait;
@@ -178,8 +179,9 @@ ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
__poll_t iio_buffer_poll(struct file *filp,
struct poll_table_struct *wait)
{
- struct iio_dev *indio_dev = filp->private_data;
- struct iio_buffer *rb = indio_dev->buffer;
+ struct iio_dev_buffer_pair *ib = filp->private_data;
+ struct iio_buffer *rb = ib->buffer;
+ struct iio_dev *indio_dev = ib->indio_dev;

if (!indio_dev->info || rb == NULL)
return 0;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 088e59042226..0d1880837776 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1666,13 +1666,24 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
{
struct iio_dev *indio_dev = container_of(inode->i_cdev,
struct iio_dev, chrdev);
+ struct iio_dev_buffer_pair *ib;

if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
return -EBUSY;

iio_device_get(indio_dev);

- filp->private_data = indio_dev;
+ ib = kmalloc(sizeof(*ib), GFP_KERNEL);
+ if (!ib) {
+ iio_device_put(indio_dev);
+ clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
+ return -ENOMEM;
+ }
+
+ ib->indio_dev = indio_dev;
+ ib->buffer = indio_dev->buffer;
+
+ filp->private_data = ib;

return 0;
}
@@ -1686,10 +1697,12 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
*/
static int iio_chrdev_release(struct inode *inode, struct file *filp)
{
+ struct iio_dev_buffer_pair *ib = filp->private_data;
struct iio_dev *indio_dev = container_of(inode->i_cdev,
struct iio_dev, chrdev);
clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
iio_device_put(indio_dev);
+ kfree(ib);

return 0;
}
@@ -1709,7 +1722,8 @@ void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h)

static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- struct iio_dev *indio_dev = filp->private_data;
+ struct iio_dev_buffer_pair *ib = filp->private_data;
+ struct iio_dev *indio_dev = ib->indio_dev;
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_ioctl_handler *h;
int ret = -ENODEV;
--
2.17.1

2021-01-22 17:12:16

by Alexandru Ardelean

[permalink] [raw]
Subject: [PATCH v2 07/12][RESEND] iio: buffer: re-route core buffer attributes via it's new kobj_type

For the buffer attributes that are present inside the IIO core buffer logic
we can re-route them to expand the attribute into iio_buffer objects.

The rest, will still expand to device_attributes.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-buffer.c | 113 +++++++++++++++++-------------
1 file changed, 64 insertions(+), 49 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 524b897a1877..8470921cf2fa 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -572,22 +572,18 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
return ret;
}

-static ssize_t iio_buffer_read_length(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_read_length(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
return sprintf(buf, "%d\n", buffer->length);
}

-static ssize_t iio_buffer_write_length(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_write_length(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
const char *buf, size_t len)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_dev *indio_dev = buffer->indio_dev;
unsigned int val;
int ret;

@@ -615,13 +611,10 @@ static ssize_t iio_buffer_write_length(struct device *dev,
return ret ? ret : len;
}

-static ssize_t iio_buffer_show_enable(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_show_enable(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
}

@@ -1227,15 +1220,14 @@ void iio_disable_all_buffers(struct iio_dev *indio_dev)
iio_buffer_deactivate_all(indio_dev);
}

-static ssize_t iio_buffer_store_enable(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_store_enable(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
const char *buf,
size_t len)
{
int ret;
bool requested_state;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_dev *indio_dev = buffer->indio_dev;
bool inlist;

ret = strtobool(buf, &requested_state);
@@ -1260,23 +1252,19 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
return (ret < 0) ? ret : len;
}

-static ssize_t iio_buffer_show_watermark(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_show_watermark(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
return sprintf(buf, "%u\n", buffer->watermark);
}

-static ssize_t iio_buffer_store_watermark(struct device *dev,
- struct device_attribute *attr,
+static ssize_t iio_buffer_store_watermark(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
const char *buf,
size_t len)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_dev *indio_dev = buffer->indio_dev;
unsigned int val;
int ret;

@@ -1305,36 +1293,51 @@ static ssize_t iio_buffer_store_watermark(struct device *dev,
return ret ? ret : len;
}

-static ssize_t iio_dma_show_data_available(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t iio_dma_show_data_available(struct iio_buffer *buffer,
+ struct iio_buf_attr *attr,
+ char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
-
return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
}

-static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
- iio_buffer_write_length);
-static struct device_attribute dev_attr_length_ro = __ATTR(length,
+#define IIO_BUF_ATTR(_name, _mode, _show, _store) \
+ struct iio_buf_attr iio_buf_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+static IIO_BUF_ATTR(length, S_IRUGO | S_IWUSR,
+ iio_buffer_read_length, iio_buffer_write_length);
+static struct iio_buf_attr buf_attr_length_ro = __ATTR(length,
S_IRUGO, iio_buffer_read_length, NULL);
-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
- iio_buffer_show_enable, iio_buffer_store_enable);
-static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
- iio_buffer_show_watermark, iio_buffer_store_watermark);
-static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark,
+static IIO_BUF_ATTR(enable, S_IRUGO | S_IWUSR,
+ iio_buffer_show_enable, iio_buffer_store_enable);
+static IIO_BUF_ATTR(watermark, S_IRUGO | S_IWUSR,
+ iio_buffer_show_watermark, iio_buffer_store_watermark);
+static struct iio_buf_attr buf_attr_watermark_ro = __ATTR(watermark,
S_IRUGO, iio_buffer_show_watermark, NULL);
-static DEVICE_ATTR(data_available, S_IRUGO,
- iio_dma_show_data_available, NULL);
+static IIO_BUF_ATTR(data_available, S_IRUGO,
+ iio_dma_show_data_available, NULL);

static struct attribute *iio_buffer_attrs[] = {
- &dev_attr_length.attr,
- &dev_attr_enable.attr,
- &dev_attr_watermark.attr,
- &dev_attr_data_available.attr,
+ &iio_buf_attr_length.attr,
+ &iio_buf_attr_enable.attr,
+ &iio_buf_attr_watermark.attr,
+ &iio_buf_attr_data_available.attr,
};

+static bool iio_buffer_attr_is_core(struct attribute *attr)
+{
+ struct attribute *a;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(iio_buffer_attrs); i++) {
+ a = iio_buffer_attrs[i];
+ if (!strcmp(attr->name, a->name))
+ return true;
+ }
+
+ return false;
+}
+
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
#define to_iio_buf_attr(_attr) container_of(_attr, struct iio_buf_attr, attr)

@@ -1344,6 +1347,12 @@ static ssize_t iio_buffer_dir_attr_show(struct kobject *kobj,
{
struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, buffer_dir);
struct device_attribute *dattr;
+ struct iio_buf_attr *battr;
+
+ if (iio_buffer_attr_is_core(attr)) {
+ battr = to_iio_buf_attr(attr);
+ return battr->show(buffer, battr, buf);
+ }

dattr = to_dev_attr(attr);

@@ -1357,6 +1366,12 @@ static ssize_t iio_buffer_dir_attr_store(struct kobject *kobj,
{
struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, buffer_dir);
struct device_attribute *dattr;
+ struct iio_buf_attr *battr;
+
+ if (iio_buffer_attr_is_core(attr)) {
+ battr = to_iio_buf_attr(attr);
+ return battr->store(buffer, battr, buf, len);
+ }

dattr = to_dev_attr(attr);

@@ -1476,10 +1491,10 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,

memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
if (!buffer->access->set_length)
- attr[0] = &dev_attr_length_ro.attr;
+ attr[0] = &buf_attr_length_ro.attr;

if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
- attr[2] = &dev_attr_watermark_ro.attr;
+ attr[2] = &buf_attr_watermark_ro.attr;

if (buffer->attrs)
memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
--
2.17.1