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
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
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
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
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
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
_______________________________________________
kbuild mailing list -- [email protected]
To unsubscribe send an email to [email protected]