2020-05-08 13:56:39

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

I blew a few fuses trying to get to this combination.
And I still don't like this one, but it works.

Some patches here [like Lars' patches] are here just make things easier
to apply when moving from the ADI tree to the upstream one.
For a final patchset I'll need to re-apply/re-test.

A working version of this patchset but also with output buffer support
is here:
https://github.com/analogdevicesinc/linux/tree/adi-iio-buffers-work
[ it's based on 4.19 ]

It will take a few more patches to bring output support to this tree,
but this should add initial support for multiple IIO buffers per device.
I haven't tested this patchset, I've tested the one in the link above.
I currently don't have [at hand] any devices that would benefit from
using multiple buffers per IIO device. Maybe when I get back to the
office.

Firstly: I need a bit of help in trying to symlink from the kernel
files in the /dev folder. I could not find any examples of how this is
done [without cracking open some deep kernel/kernfs code], so maybe it's
done via userspace?
Any suggestions are welcome.

I noticed that symlinking via sysfs_create_link() is fine outside of the
fs/ folder, so that's what I used.

I think I also partially understand why Lars was initially against doing
this 'multiple IIO buffers per IIO device'.
I've tried various combinations of doing things, and nothing fits
perfect, without feeling like I'm doing some sort of mini-frankenstein,
just in order to preserve some backwards compatibility.

So, to make this work, what I need to do now, is:
------------
root@analog:~# cd /dev/
root@analog:/dev# ln -s iio\:buffer3\:0 iio\:device3
root@analog:/dev# ln -s iio\:buffer4\:0 iio\:device4
root@analog:/dev# ls | grep iio
iio:buffer3:0
iio:buffer3:1
iio:buffer3:2
iio:buffer3:3
iio:buffer4:0
iio:device0
iio:device1
iio:device3
iio:device4
------------

device3 is an ADC with 4 buffers attached, only the first one is
currently being used (in legacy mode); the other 3 aren't being used.

The IIO buffer devices are named '/dev/iio:bufferX:Y', X being the
ID of the IIO device, and Y being the ID of the buffer of device X.
These could be renamed to '/dev/iio:deviceX:Y', but that would be
confusing I guess.

Then
------------
root@analog:/# ls /sys/bus/iio/devices/
iio:buffer3:0 iio:buffer3:1 iio:buffer3:2 iio:buffer3:3 iio:buffer4:0 iio:device0 iio:device1 iio:device2 iio:device3 iio:device4
------------
root@analog:/# ls /sys/bus/iio/devices/iio:buffer3:0
data_available dev enable length length_align_bytes power scan_elements subsystem uevent watermark
------------
root@analog:/# ls -la /sys/bus/iio/devices/iio\:device3/
total 0
drwxr-xr-x 8 root root 0 May 8 13:00 .
drwxr-xr-x 4 root root 0 May 8 12:53 ..
lrwxrwxrwx 1 root root 0 May 8 13:00 buffer -> iio:buffer3:0
drwxrwxrwx 2 root root 0 May 8 12:53 events
drwxrwxrwx 4 root root 0 May 8 12:53 iio:buffer3:0
drwxrwxrwx 4 root root 0 May 8 12:53 iio:buffer3:1
drwxrwxrwx 4 root root 0 May 8 12:53 iio:buffer3:2
drwxrwxrwx 4 root root 0 May 8 12:53 iio:buffer3:3
-rw-rw-rw- 1 root root 4096 May 8 12:54 in_voltage0_test_mode
-rw-rw-rw- 1 root root 4096 May 8 12:54 in_voltage1_test_mode
-rw-rw-rw- 1 root root 4096 May 8 12:54 in_voltage_sampling_frequency
-rw-rw-rw- 1 root root 4096 May 8 12:53 in_voltage_scale
-rw-rw-rw- 1 root root 4096 May 8 12:53 in_voltage_scale_available
-rw-rw-rw- 1 root root 4096 May 8 12:53 in_voltage_test_mode_available
-rw-rw-rw- 1 root root 4096 May 8 12:53 name
lrwxrwxrwx 1 root root 0 May 8 13:00 of_node -> ../../../../../firmware/devicetree/base/fpga-axi@0/axi-ad9680-hpc@44a10000
drwxrwxrwx 2 root root 0 May 8 12:53 power
lrwxrwxrwx 1 root root 0 May 8 13:00 scan_elements -> iio:buffer3:0/scan_elements
lrwxrwxrwx 1 root root 0 May 8 13:00 subsystem -> ../../../../../bus/iio
-rw-rw-rw- 1 root root 4096 May 8 12:53 uevent
------------
root@analog:/# ls -la /sys/bus/iio/devices/iio:device3/iio:buffer3:0/
total 0
drwxrwxrwx 4 root root 0 May 8 12:53 .
drwxr-xr-x 8 root root 0 May 8 13:00 ..
-rw-rw-rw- 1 root root 4096 May 8 12:53 data_available
-rw-rw-rw- 1 root root 4096 May 8 12:53 dev
-rw-rw-rw- 1 root root 4096 May 8 12:53 enable
-rw-rw-rw- 1 root root 4096 May 8 12:53 length
-rw-rw-rw- 1 root root 4096 May 8 12:53 length_align_bytes
drwxrwxrwx 2 root root 0 May 8 12:53 power
drwxrwxrwx 2 root root 0 May 8 12:53 scan_elements
lrwxrwxrwx 1 root root 0 May 8 12:53 subsystem -> ../../../../../../bus/iio
-rw-rw-rw- 1 root root 4096 May 8 12:53 uevent
-rw-rw-rw- 1 root root 4096 May 8 12:53 watermark
------------

Using our fancy IIO-oscilloscope[1] app with this format, seems to work.
[1] https://github.com/analogdevicesinc/iio-oscilloscope

Linking the 'scan_elements' folder from the first buffer looks a
bit fishy [the code I mean]; it requires that the buffer device be added
first, so that the 'scan_elements' be attached via kobject, so that we
can have the kobject (as a symlink target).
Again, I did not want to crack open the kernfs.

What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
This is because the 'buffer->dev.parent = &indio_dev->dev'.
But I do feel this is correct.
So, now I don't know whether to leave it like that or symlink to shorter
versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
mostly to make the names unique. It would have looked weird to do
'/dev/buffer1' if I would have named the buffer devices 'bufferX'.

So, now I'm thinking of whether all this is acceptable.
Or what is acceptable?
Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
What else should I consider moving forward?
What means forward?
Where did I leave my beer?

Well, if you've found my beer, it means you got this far :)
Thanks for reading all of this [including this bit of quarantine humor].

Alexandru Ardelean (12):
iio: buffer: add back-ref from iio_buffer to iio_dev
iio: core,buffer: wrap iio_buffer_put() call into iio_buffers_put()
iio: core: register chardev only if needed
iio: buffer,event: duplicate chardev creation for buffers & events
iio: core: add simple centralized mechanism for ioctl() handlers
iio: core: use new common ioctl() mechanism
iio: buffer: split buffer sysfs creation to take buffer as primary arg
iio: buffer: remove attrcount_orig var from sysfs creation
iio: buffer: add underlying device object and convert buffers to
devices
iio: buffer: symlink the scan_elements dir back into IIO device's dir
iio: unpack all iio buffer attributes correctly
iio: buffer: convert single buffer to list of buffers

Lars-Peter Clausen (2):
iio: Move scan mask management to the core
iio: hw_consumer: use new scanmask functions

drivers/iio/accel/adxl372.c | 6 +-
drivers/iio/accel/bmc150-accel-core.c | 6 +-
drivers/iio/buffer/industrialio-buffer-cb.c | 16 +-
.../buffer/industrialio-buffer-dmaengine.c | 4 +-
drivers/iio/buffer/industrialio-hw-consumer.c | 19 +-
drivers/iio/iio_core.h | 40 +-
drivers/iio/industrialio-buffer.c | 468 ++++++++++++++----
drivers/iio/industrialio-core.c | 174 +++----
drivers/iio/industrialio-event.c | 100 +++-
drivers/iio/inkern.c | 15 +
include/linux/iio/buffer.h | 3 +
include/linux/iio/buffer_impl.h | 24 +-
include/linux/iio/consumer.h | 10 +
include/linux/iio/iio.h | 12 +-
14 files changed, 688 insertions(+), 209 deletions(-)

--
2.17.1


2020-05-08 13:56:48

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 11/14] iio: buffer: add underlying device object and convert buffers to devices

WIP

Currently, IIO is broken here.
Each buffer is now an object.
The part where this is broken is backwards compatibility.
We need to:
- convert all external buffer attributes to unpack to IIO buffers and not
IIO devices
- symlink the 'scan_elements' folder of the (first) IIO buffer device to
the IIO device
- symlink the chardev of the first IIO buffer device to the IIO device

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/iio_core.h | 11 ++--
drivers/iio/industrialio-buffer.c | 98 ++++++++++++++++++++++++-------
drivers/iio/industrialio-core.c | 39 +++++++-----
include/linux/iio/buffer_impl.h | 6 ++
include/linux/iio/iio.h | 2 +-
5 files changed, 116 insertions(+), 40 deletions(-)

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index f68de4af2738..890577766f9b 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -54,10 +54,13 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
#ifdef CONFIG_IIO_BUFFER
struct poll_table_struct;

+int iio_device_alloc_chrdev_id(struct device *dev);
+void iio_device_free_chrdev_id(struct device *dev);
+
void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev);

-int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
-void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev);
+int iio_device_buffers_init(struct iio_dev *indio_dev);
+void iio_device_buffers_cleanup(struct iio_dev *indio_dev);

void iio_device_buffers_put(struct iio_dev *indio_dev);

@@ -68,12 +71,12 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);

static inline void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev) {}

-static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
+static inline int iio_device_buffers_init(struct iio_dev *indio_dev)
{
return 0;
}

-static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {}
+static inline void iio_device_buffers_cleanup(struct iio_dev *indio_dev) {}

static inline void iio_device_buffers_put(struct iio_dev *indio_dev) {}

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index efebf74a05af..6c35de7ebd9e 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1235,8 +1235,6 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
return (ret < 0) ? ret : len;
}

-static const char * const iio_scan_elements_group_name = "scan_elements";
-
static ssize_t iio_buffer_show_watermark(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1312,7 +1310,7 @@ static struct attribute *iio_buffer_attrs[] = {
&dev_attr_data_available.attr,
};

-static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
+static int iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
{
struct iio_dev *indio_dev = buffer->indio_dev;
struct iio_dev_attr *p;
@@ -1344,10 +1342,9 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)

attr[attrcount + ARRAY_SIZE(iio_buffer_attrs)] = NULL;

- buffer->buffer_group.name = "buffer";
buffer->buffer_group.attrs = attr;

- indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
+ buffer->groups[0] = &buffer->buffer_group;

attrcount = 0;
INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
@@ -1373,7 +1370,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
goto error_cleanup_dynamic;
}

- buffer->scan_el_group.name = iio_scan_elements_group_name;
+ buffer->scan_el_group.name = "scan_elements";

buffer->scan_el_group.attrs = kcalloc(attrcount + 1,
sizeof(buffer->scan_el_group.attrs[0]),
@@ -1386,7 +1383,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)

list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr;
- indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group;
+ buffer->groups[1] = &buffer->scan_el_group;

return 0;

@@ -1399,11 +1396,66 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
return ret;
}

-int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
+static void iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
+{
+ iio_buffer_free_scanmask(buffer);
+ kfree(buffer->buffer_group.attrs);
+ kfree(buffer->scan_el_group.attrs);
+ iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
+}
+
+static int iio_device_buffer_init(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer,
+ int index)
+{
+ int ret;
+
+ ret = iio_buffer_alloc_sysfs_and_mask(buffer);
+ if (ret)
+ return ret;
+
+ ret = iio_device_alloc_chrdev_id(&buffer->dev);
+ if (ret)
+ goto error_free_sysfs_and_mask;
+
+ buffer->dev.parent = &indio_dev->dev;
+ buffer->dev.groups = buffer->groups;
+ buffer->dev.bus = &iio_bus_type;
+ device_initialize(&buffer->dev);
+
+ dev_set_name(&buffer->dev, "iio:buffer%d:%d",
+ indio_dev->id, index);
+
+ ret = cdev_device_add(&buffer->chrdev, &buffer->dev);
+ if (ret)
+ goto error_free_chrdev_id;
+
+ return 0;
+
+error_free_chrdev_id:
+ iio_device_free_chrdev_id(&buffer->dev);
+error_free_sysfs_and_mask:
+ iio_buffer_free_sysfs_and_mask(buffer);
+ return ret;
+}
+
+void iio_device_buffer_cleanup(struct iio_buffer *buffer)
+{
+ if (!buffer)
+ return;
+
+ iio_buffer_free_sysfs_and_mask(buffer);
+
+ cdev_device_del(&buffer->chrdev, &buffer->dev);
+
+ iio_device_free_chrdev_id(&buffer->dev);
+}
+
+int iio_device_buffers_init(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer = indio_dev->buffer;
const struct iio_chan_spec *channels;
- int i;
+ int i, ret;

channels = indio_dev->channels;
if (channels) {
@@ -1417,25 +1469,29 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
if (!buffer)
return 0;

- return __iio_buffer_alloc_sysfs_and_mask(buffer);
-}
+ ret = iio_device_buffer_init(indio_dev, buffer, 0);
+ if (ret)
+ return ret;

-static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
-{
- iio_buffer_free_scanmask(buffer);
- kfree(buffer->buffer_group.attrs);
- kfree(buffer->scan_el_group.attrs);
- iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
+ ret = sysfs_create_link(&indio_dev->dev.kobj,
+ &buffer->dev.kobj, "buffer");
+ if (ret)
+ goto error_cleanup_buffers;
+
+ return 0;
+
+error_cleanup_buffers:
+ iio_device_buffer_cleanup(buffer);
+ return 0;
}

-void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
+void iio_device_buffers_cleanup(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer = indio_dev->buffer;

- if (!buffer)
- return;
+ sysfs_remove_link(&indio_dev->dev.kobj, "buffer");

- __iio_buffer_free_sysfs_and_mask(buffer);
+ iio_device_buffer_cleanup(buffer);
}

static const struct file_operations iio_buffer_fileops = {
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 5df3af5e7dcb..b27fabf13e9c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1638,7 +1638,7 @@ static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
return 0;
}

-static int iio_device_alloc_chrdev_id(struct device *dev)
+int iio_device_alloc_chrdev_id(struct device *dev)
{
int id;

@@ -1654,7 +1654,7 @@ static int iio_device_alloc_chrdev_id(struct device *dev)
return 0;
}

-static void iio_device_free_chrdev_id(struct device *dev)
+void iio_device_free_chrdev_id(struct device *dev)
{
if (!dev->devt)
return;
@@ -1684,18 +1684,11 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)

iio_device_register_debugfs(indio_dev);

- ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
- if (ret) {
- dev_err(indio_dev->dev.parent,
- "Failed to create buffer sysfs interfaces\n");
- goto error_unreg_debugfs;
- }
-
ret = iio_device_register_sysfs(indio_dev);
if (ret) {
dev_err(indio_dev->dev.parent,
"Failed to register sysfs interfaces\n");
- goto error_buffer_free_sysfs;
+ goto error_unreg_debugfs;
}
ret = iio_device_register_eventset(indio_dev);
if (ret) {
@@ -1712,6 +1705,26 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)

iio_device_buffer_attach_chrdev(indio_dev);

+ if (indio_dev->chrdev) {
+ ret = device_add(&indio_dev->dev);
+
+ if (ret) {
+ put_device(&indio_dev->dev);
+ goto error_unreg_eventset;
+ }
+
+ ret = iio_device_buffers_init(indio_dev);
+ if (ret) {
+ device_del(&indio_dev->dev);
+
+ dev_err(indio_dev->dev.parent,
+ "Failed to create buffer sysfs interfaces\n");
+ goto error_unreg_eventset;
+ }
+
+ return 0;
+ }
+
/* No chrdev attached from buffer, we go with event-only chrdev */
if (!indio_dev->chrdev)
iio_device_event_attach_chrdev(indio_dev);
@@ -1736,8 +1749,6 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
iio_device_unregister_eventset(indio_dev);
error_free_sysfs:
iio_device_unregister_sysfs(indio_dev);
-error_buffer_free_sysfs:
- iio_buffer_free_sysfs_and_mask(indio_dev);
error_unreg_debugfs:
iio_device_unregister_debugfs(indio_dev);
return ret;
@@ -1752,6 +1763,8 @@ void iio_device_unregister(struct iio_dev *indio_dev)
{
struct iio_ioctl_handler *h, *t;

+ iio_device_buffers_cleanup(indio_dev);
+
cdev_device_del(indio_dev->chrdev, &indio_dev->dev);
iio_device_free_chrdev_id(&indio_dev->dev);

@@ -1770,8 +1783,6 @@ void iio_device_unregister(struct iio_dev *indio_dev)
iio_buffer_wakeup_poll(indio_dev);

mutex_unlock(&indio_dev->info_exist_lock);
-
- iio_buffer_free_sysfs_and_mask(indio_dev);
}
EXPORT_SYMBOL(iio_device_unregister);

diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h
index 46fc977deae3..eca3fe630230 100644
--- a/include/linux/iio/buffer_impl.h
+++ b/include/linux/iio/buffer_impl.h
@@ -104,6 +104,12 @@ struct iio_buffer {
unsigned int watermark;

/* private: */
+ /* @dev: underlying device object. */
+ struct device dev;
+
+#define IIO_BUFFER_MAX_GROUP 2
+ const struct attribute_group *groups[IIO_BUFFER_MAX_GROUP + 1];
+
/* @scan_timestamp: Does the scan mode include a timestamp. */
bool scan_timestamp;

diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index b6ca8d85629e..671f5818fa67 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -561,7 +561,7 @@ struct iio_dev {
struct mutex info_exist_lock;
const struct iio_buffer_setup_ops *setup_ops;
struct cdev *chrdev;
-#define IIO_MAX_GROUPS 6
+#define IIO_MAX_GROUPS 5
const struct attribute_group *groups[IIO_MAX_GROUPS + 1];
int groupcounter;

--
2.17.1

2020-05-08 13:56:51

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 12/14] iio: buffer: symlink the scan_elements dir back into IIO device's dir

WIP

Need to explicitly create the scan_elements dir to symlink it.
Admittedly we could try to use some kernfs logic to dig out the kobject of
the 'scan_elements' group, it doesn't seem to be done outside of the fs/
kernel directory.

We need to use the sysfs_() function suite, and that means creating it by
hand after the IIO buffer device was created and added so that we have a
parent kobject to attach this folder to.

After we create it by hand there is a kobject to which to symlink this to
back to the IIO device.

IIO still broken
What's left:
- convert all external buffer attributes to unpack to IIO buffers and not
IIO devices
- symlink the chardev of the first IIO buffer device to the IIO device

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

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 6c35de7ebd9e..b14281442387 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1310,15 +1310,11 @@ static struct attribute *iio_buffer_attrs[] = {
&dev_attr_data_available.attr,
};

-static int iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
+static int iio_buffer_alloc_sysfs(struct iio_buffer *buffer)
{
- struct iio_dev *indio_dev = buffer->indio_dev;
- struct iio_dev_attr *p;
struct attribute **attr;
- int ret, i, attrn, attrcount;
- const struct iio_chan_spec *channels;
+ int attrcount = 0;

- attrcount = 0;
if (buffer->attrs) {
while (buffer->attrs[attrcount] != NULL)
attrcount++;
@@ -1346,7 +1342,60 @@ static int iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)

buffer->groups[0] = &buffer->buffer_group;

- attrcount = 0;
+ return 0;
+}
+
+static ssize_t iio_scan_el_dir_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct device_attribute *dattr =
+ container_of(attr, struct device_attribute, attr);
+ struct iio_buffer *buffer =
+ container_of(kobj, struct iio_buffer, scan_el_dir);
+
+ if (!dattr->show)
+ return -EIO;
+
+ return dattr->show(&buffer->dev, dattr, buf);
+}
+
+static ssize_t iio_scan_el_dir_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf, size_t len)
+{
+ struct device_attribute *dattr =
+ container_of(attr, struct device_attribute, attr);
+ struct iio_buffer *buffer =
+ container_of(kobj, struct iio_buffer, scan_el_dir);
+
+ if (!dattr->store)
+ return -EIO;
+
+ return dattr->store(&buffer->dev, dattr, buf, len);
+}
+
+static struct sysfs_ops iio_scan_el_dir_ops = {
+ .show = iio_scan_el_dir_show,
+ .store = iio_scan_el_dir_store,
+};
+
+static void iio_buffer_dir_noop_release(struct kobject *kobj)
+{
+ /* nothing to do yet */
+}
+
+static struct kobj_type iio_scan_el_dir_ktype = {
+ .release = iio_buffer_dir_noop_release,
+ .sysfs_ops = &iio_scan_el_dir_ops,
+};
+
+static int iio_buffer_alloc_scan_sysfs(struct iio_buffer *buffer)
+{
+ struct iio_dev *indio_dev = buffer->indio_dev;
+ struct iio_dev_attr *p;
+ int ret, i;
+ const struct iio_chan_spec *channels;
+
INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
channels = indio_dev->channels;
if (channels) {
@@ -1359,7 +1408,6 @@ static int iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
&channels[i]);
if (ret < 0)
goto error_cleanup_dynamic;
- attrcount += ret;
if (channels[i].type == IIO_TIMESTAMP)
indio_dev->scan_index_timestamp =
channels[i].scan_index;
@@ -1370,37 +1418,52 @@ static int iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
goto error_cleanup_dynamic;
}

- buffer->scan_el_group.name = "scan_elements";
-
- buffer->scan_el_group.attrs = kcalloc(attrcount + 1,
- sizeof(buffer->scan_el_group.attrs[0]),
- GFP_KERNEL);
- if (buffer->scan_el_group.attrs == NULL) {
- ret = -ENOMEM;
+ ret = kobject_init_and_add(&buffer->scan_el_dir,
+ &iio_scan_el_dir_ktype, &buffer->dev.kobj,
+ "scan_elements");
+ if (ret)
goto error_free_scan_mask;
- }
- attrn = 0;

- list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
- buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr;
- buffer->groups[1] = &buffer->scan_el_group;
+ i = 0;
+ list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) {
+ ret = sysfs_create_file(&buffer->scan_el_dir,
+ &p->dev_attr.attr);
+ if (ret)
+ goto error_remove_scan_el_dir;
+ i++;
+ }

return 0;

+error_remove_scan_el_dir:
+ list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) {
+ if (i == 0)
+ break;
+ sysfs_remove_file(&buffer->scan_el_dir, &p->dev_attr.attr);
+ i--;
+ }
+ kobject_put(&buffer->scan_el_dir);
error_free_scan_mask:
iio_buffer_free_scanmask(buffer);
error_cleanup_dynamic:
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
- kfree(buffer->buffer_group.attrs);

return ret;
}

-static void iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
+static void iio_buffer_free_sysfs(struct iio_buffer *buffer)
{
iio_buffer_free_scanmask(buffer);
kfree(buffer->buffer_group.attrs);
- kfree(buffer->scan_el_group.attrs);
+}
+
+static void iio_buffer_free_scan_sysfs(struct iio_buffer *buffer)
+{
+ struct iio_dev_attr *p;
+
+ list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
+ sysfs_remove_file(&buffer->scan_el_dir, &p->dev_attr.attr);
+ kobject_put(&buffer->scan_el_dir);
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
}

@@ -1410,7 +1473,7 @@ static int iio_device_buffer_init(struct iio_dev *indio_dev,
{
int ret;

- ret = iio_buffer_alloc_sysfs_and_mask(buffer);
+ ret = iio_buffer_alloc_sysfs(buffer);
if (ret)
return ret;

@@ -1430,12 +1493,18 @@ static int iio_device_buffer_init(struct iio_dev *indio_dev,
if (ret)
goto error_free_chrdev_id;

+ ret = iio_buffer_alloc_scan_sysfs(buffer);
+ if (ret)
+ goto error_cdev_device_del;
+
return 0;

+error_cdev_device_del:
+ cdev_device_del(&buffer->chrdev, &buffer->dev);
error_free_chrdev_id:
iio_device_free_chrdev_id(&buffer->dev);
error_free_sysfs_and_mask:
- iio_buffer_free_sysfs_and_mask(buffer);
+ iio_buffer_free_sysfs(buffer);
return ret;
}

@@ -1444,13 +1513,33 @@ void iio_device_buffer_cleanup(struct iio_buffer *buffer)
if (!buffer)
return;

- iio_buffer_free_sysfs_and_mask(buffer);
+ iio_buffer_free_scan_sysfs(buffer);

cdev_device_del(&buffer->chrdev, &buffer->dev);

+ iio_buffer_free_sysfs(buffer);
+
iio_device_free_chrdev_id(&buffer->dev);
}

+static int iio_device_link_legacy_folders(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer)
+{
+ int ret;
+
+ ret = sysfs_create_link(&indio_dev->dev.kobj,
+ &buffer->dev.kobj, "buffer");
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_link(&indio_dev->dev.kobj,
+ &buffer->scan_el_dir, "scan_elements");
+ if (ret)
+ sysfs_remove_link(&indio_dev->dev.kobj, "buffer");
+
+ return ret;
+}
+
int iio_device_buffers_init(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer = indio_dev->buffer;
@@ -1473,14 +1562,13 @@ int iio_device_buffers_init(struct iio_dev *indio_dev)
if (ret)
return ret;

- ret = sysfs_create_link(&indio_dev->dev.kobj,
- &buffer->dev.kobj, "buffer");
+ ret = iio_device_link_legacy_folders(indio_dev, buffer);
if (ret)
- goto error_cleanup_buffers;
+ goto error_buffers_cleanup;

return 0;

-error_cleanup_buffers:
+error_buffers_cleanup:
iio_device_buffer_cleanup(buffer);
return 0;
}
@@ -1490,6 +1578,7 @@ void iio_device_buffers_cleanup(struct iio_dev *indio_dev)
struct iio_buffer *buffer = indio_dev->buffer;

sysfs_remove_link(&indio_dev->dev.kobj, "buffer");
+ sysfs_remove_link(&indio_dev->dev.kobj, "scan_elements");

iio_device_buffer_cleanup(buffer);
}
diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h
index eca3fe630230..e8203b6d51a1 100644
--- a/include/linux/iio/buffer_impl.h
+++ b/include/linux/iio/buffer_impl.h
@@ -107,7 +107,7 @@ struct iio_buffer {
/* @dev: underlying device object. */
struct device dev;

-#define IIO_BUFFER_MAX_GROUP 2
+#define IIO_BUFFER_MAX_GROUP 1
const struct attribute_group *groups[IIO_BUFFER_MAX_GROUP + 1];

/* @scan_timestamp: Does the scan mode include a timestamp. */
@@ -120,10 +120,9 @@ struct iio_buffer {
struct attribute_group buffer_group;

/*
- * @scan_el_group: Attribute group for those attributes not
- * created from the iio_chan_info array.
+ * @scan_el_dir: kobject for the 'scan_elements' directory
*/
- struct attribute_group scan_el_group;
+ struct kobject scan_el_dir;

/* @attrs: Standard attributes of the buffer. */
const struct attribute **attrs;
--
2.17.1

2020-05-08 13:56:56

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 13/14] iio: unpack all iio buffer attributes correctly

WIP

This change fixes how IIO buffer attributes get unpacked.
There could be a saner way to unpack these without needed to change the
drivers that attach buffer attributes incorrectly via
iio_buffer_set_attrs()

It seems that the design idea was that there is a single buffer per IIO
device, so all drivers attached buffer attributes for FIFO to the IIO
buffer.

Now with the change to add a device object to the IIO buffer, and shifting
around the device-attributes, a 'device' object unpacks to an IIO buffer
object, which needs some special handling.'

One idea to fix this, is to get rid of iio_buffer_set_attrs() somehow.
Or, to maybe allocate some wrapper device-attributes.

With this change, IIO still needs (to work with the older ABI):
- symlink the chardev of the first IIO buffer device to the IIO device

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/accel/adxl372.c | 6 ++-
drivers/iio/accel/bmc150-accel-core.c | 6 ++-
.../buffer/industrialio-buffer-dmaengine.c | 4 +-
drivers/iio/industrialio-buffer.c | 51 +++++++++++--------
include/linux/iio/buffer.h | 3 ++
5 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 60daf04ce188..528bce008671 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -745,7 +745,8 @@ static ssize_t adxl372_get_fifo_enabled(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
struct adxl372_state *st = iio_priv(indio_dev);

return sprintf(buf, "%d\n", st->fifo_mode);
@@ -755,7 +756,8 @@ static ssize_t adxl372_get_fifo_watermark(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
struct adxl372_state *st = iio_priv(indio_dev);

return sprintf(buf, "%d\n", st->watermark);
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 121b4e89f038..c02287165980 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -763,7 +763,8 @@ static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
struct bmc150_accel_data *data = iio_priv(indio_dev);
int wm;

@@ -778,7 +779,8 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
struct bmc150_accel_data *data = iio_priv(indio_dev);
bool state;

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 6dedf12b69a4..7728fdadcc3e 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -130,9 +130,9 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = {
static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = dev_to_iio_buffer(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);
}
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index b14281442387..aa2f46c0949f 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -29,6 +29,19 @@ static const char * const iio_endian_prefix[] = {
[IIO_LE] = "le",
};

+struct iio_buffer *dev_to_iio_buffer(struct device *dev)
+{
+ return container_of(dev, struct iio_buffer, dev);
+}
+EXPORT_SYMBOL_GPL(dev_to_iio_buffer);
+
+struct iio_dev *iio_buffer_get_attached_iio_dev(struct iio_buffer *buffer)
+{
+ return buffer ? NULL : buffer->indio_dev;
+}
+EXPORT_SYMBOL_GPL(iio_buffer_get_attached_iio_dev);
+
+
static bool iio_buffer_is_active(struct iio_buffer *buf)
{
return !list_empty(&buf->buffer_list);
@@ -324,9 +337,8 @@ static ssize_t iio_scan_el_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
int ret;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;

/* Ensure ret is 0 or 1. */
ret = !!test_bit(to_iio_dev_attr(attr)->address,
@@ -436,10 +448,10 @@ static ssize_t iio_scan_el_store(struct device *dev,
const char *buf,
size_t len)
{
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = buffer->indio_dev;
int ret;
bool state;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);

ret = strtobool(buf, &state);
@@ -474,8 +486,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);

return sprintf(buf, "%d\n", buffer->scan_timestamp);
}
@@ -485,9 +496,9 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
const char *buf,
size_t len)
{
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = buffer->indio_dev;
int ret;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
bool state;

ret = strtobool(buf, &state);
@@ -563,8 +574,7 @@ static ssize_t iio_buffer_read_length(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);

return sprintf(buf, "%d\n", buffer->length);
}
@@ -573,8 +583,8 @@ static ssize_t iio_buffer_write_length(struct device *dev,
struct device_attribute *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_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = buffer->indio_dev;
unsigned int val;
int ret;

@@ -606,8 +616,7 @@ static ssize_t iio_buffer_show_enable(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);

return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
}
@@ -1207,10 +1216,10 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
const char *buf,
size_t len)
{
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = buffer->indio_dev;
int ret;
bool requested_state;
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
bool inlist;

ret = strtobool(buf, &requested_state);
@@ -1239,8 +1248,7 @@ static ssize_t iio_buffer_show_watermark(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);

return sprintf(buf, "%u\n", buffer->watermark);
}
@@ -1250,8 +1258,8 @@ static ssize_t iio_buffer_store_watermark(struct device *dev,
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_buffer *buffer = dev_to_iio_buffer(dev);
+ struct iio_dev *indio_dev = buffer->indio_dev;
unsigned int val;
int ret;

@@ -1284,8 +1292,7 @@ static ssize_t iio_dma_show_data_available(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *buffer = dev_to_iio_buffer(dev);

return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
}
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index fbba4093f06c..a688e98c694c 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -11,6 +11,9 @@

struct iio_buffer;

+struct iio_buffer *dev_to_iio_buffer(struct device *dev);
+struct iio_dev *iio_buffer_get_attached_iio_dev(struct iio_buffer *buffer);
+
void iio_buffer_set_attrs(struct iio_buffer *buffer,
const struct attribute **attrs);

--
2.17.1

2020-05-08 13:57:08

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 08/14] iio: core: use new common ioctl() mechanism

This change makes use of the new centralized ioctl() mechanism. The event
interface registers it's ioctl() handler to IIO device.
Both the buffer & event interface call 'iio_device_ioctl()', which should
take care of all of indio_dev's ioctl() calls.

Later, we may add per-buffer ioctl() calls, and since each buffer will get
it's own chardev, the buffer ioctl() handler will need a bit of tweaking
for the first/legacy buffer (i.e. indio_dev->buffer).
Also, those per-buffer ioctl() calls will not be registered with this
mechanism.

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

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 34c3e19229d8..f68de4af2738 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -54,9 +54,6 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
#ifdef CONFIG_IIO_BUFFER
struct poll_table_struct;

-long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev);

int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 1400688f5e42..e7a847e7b103 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1199,7 +1199,7 @@ static long iio_buffer_ioctl(struct file *filep, unsigned int cmd,
if (!buffer || !buffer->access)
return -ENODEV;

- return iio_device_event_ioctl(buffer->indio_dev, filep, cmd, arg);
+ return iio_device_ioctl(buffer->indio_dev, filep, cmd, arg);
}

static ssize_t iio_buffer_store_enable(struct device *dev,
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 0674b2117c98..1961c1d19370 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -32,6 +32,7 @@
* @read_lock: lock to protect kfifo read operations
* @chrdev: associated chardev for this event
* @indio_dev: IIO device to which this event interface belongs to
+ * @ioctl_handler: handler for event ioctl() calls
*/
struct iio_event_interface {
wait_queue_head_t wait;
@@ -44,6 +45,7 @@ struct iio_event_interface {

struct cdev chrdev;
struct iio_dev *indio_dev;
+ struct iio_ioctl_handler ioctl_handler;
};

bool iio_event_enabled(const struct iio_event_interface *ev_int)
@@ -261,15 +263,12 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp)
return 0;
}

-long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
+static long iio_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int __user *ip = (int __user *)arg;
int fd;

- if (!indio_dev->info)
- return -ENODEV;
-
if (cmd == IIO_GET_EVENT_FD_IOCTL) {
fd = iio_event_getfd(indio_dev);
if (fd < 0)
@@ -278,7 +277,7 @@ long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
return -EFAULT;
return 0;
}
- return -EINVAL;
+ return IIO_IOCTL_UNHANDLED;
}

static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
@@ -286,7 +285,7 @@ static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
{
struct iio_event_interface *ev = filp->private_data;

- return iio_device_event_ioctl(ev->indio_dev, filp, cmd, arg);
+ return iio_device_ioctl(ev->indio_dev, filp, cmd, arg);
}

static const struct file_operations iio_event_fileops = {
@@ -308,7 +307,10 @@ void iio_device_event_attach_chrdev(struct iio_dev *indio_dev)
cdev_init(&ev->chrdev, &iio_event_fileops);

ev->indio_dev = indio_dev;
+ ev->ioctl_handler.ioctl = iio_event_ioctl;
indio_dev->chrdev = &ev->chrdev;
+
+ iio_device_ioctl_handler_register(indio_dev, &ev->ioctl_handler);
}

static const char * const iio_ev_type_text[] = {
--
2.17.1

2020-05-08 13:57:09

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 14/14] iio: buffer: convert single buffer to list of buffers

WIP

Time to add support for multiple buffers.
At this point it should be just managing a list.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-buffer.c | 74 ++++++++++++++++++++++---------
drivers/iio/industrialio-core.c | 1 +
include/linux/iio/buffer_impl.h | 3 ++
include/linux/iio/iio.h | 2 +
4 files changed, 58 insertions(+), 22 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index aa2f46c0949f..c335484a6651 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -244,12 +244,13 @@ static int iio_buffer_chrdev_release(struct inode *inode, struct file *filp)
*/
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
{
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *b;

- if (!buffer)
+ if (list_empty(&indio_dev->attached_buffers))
return;

- wake_up(&buffer->pollq);
+ list_for_each_entry(b, &indio_dev->attached_buffers, attached_entry)
+ wake_up(&b->pollq);
}

void iio_buffer_init(struct iio_buffer *buffer)
@@ -1547,10 +1548,27 @@ static int iio_device_link_legacy_folders(struct iio_dev *indio_dev,
return ret;
}

+static void __iio_device_buffers_cleanup(struct iio_dev *indio_dev, int idx)
+{
+ struct iio_buffer *b;
+
+ if (list_empty(&indio_dev->attached_buffers))
+ return;
+
+ list_for_each_entry(b, &indio_dev->attached_buffers, attached_entry) {
+ if (idx == 0)
+ break;
+
+ iio_device_buffer_cleanup(b);
+ if (idx > 0)
+ idx--;
+ }
+}
+
int iio_device_buffers_init(struct iio_dev *indio_dev)
{
- struct iio_buffer *buffer = indio_dev->buffer;
const struct iio_chan_spec *channels;
+ struct iio_buffer *b;
int i, ret;

channels = indio_dev->channels;
@@ -1562,32 +1580,38 @@ int iio_device_buffers_init(struct iio_dev *indio_dev)
indio_dev->masklength = ml;
}

- if (!buffer)
+ if (list_empty(&indio_dev->attached_buffers))
return 0;

- ret = iio_device_buffer_init(indio_dev, buffer, 0);
- if (ret)
- return ret;
+ i = 0;
+ list_for_each_entry(b, &indio_dev->attached_buffers, attached_entry) {
+ ret = iio_device_buffer_init(indio_dev, b, i);
+ if (ret)
+ goto error_buffers_cleanup;

- ret = iio_device_link_legacy_folders(indio_dev, buffer);
- if (ret)
- goto error_buffers_cleanup;
+ if (i == 0) {
+ ret = iio_device_link_legacy_folders(indio_dev, b);
+ if (ret) {
+ iio_device_buffer_cleanup(b);
+ goto error_buffers_cleanup;
+ }
+ }
+ i++;
+ }

return 0;

error_buffers_cleanup:
- iio_device_buffer_cleanup(buffer);
- return 0;
+ __iio_device_buffers_cleanup(indio_dev, i);
+ return ret;
}

void iio_device_buffers_cleanup(struct iio_dev *indio_dev)
{
- struct iio_buffer *buffer = indio_dev->buffer;
-
sysfs_remove_link(&indio_dev->dev.kobj, "buffer");
sysfs_remove_link(&indio_dev->dev.kobj, "scan_elements");

- iio_device_buffer_cleanup(buffer);
+ __iio_device_buffers_cleanup(indio_dev, -1);
}

static const struct file_operations iio_buffer_fileops = {
@@ -1615,12 +1639,13 @@ void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev)

void iio_device_buffers_put(struct iio_dev *indio_dev)
{
- struct iio_buffer *buffer = indio_dev->buffer;
+ struct iio_buffer *b;

- if (!buffer)
+ if (list_empty(&indio_dev->attached_buffers))
return;

- iio_buffer_put(buffer);
+ list_for_each_entry(b, &indio_dev->attached_buffers, attached_entry)
+ iio_buffer_put(b);
}

/**
@@ -1733,7 +1758,7 @@ void iio_buffer_put(struct iio_buffer *buffer)
EXPORT_SYMBOL_GPL(iio_buffer_put);

/**
- * iio_device_attach_buffer - Attach a buffer to a IIO device
+ * iio_device_attach_buffer_dir - Attach a buffer to a IIO device direction
* @indio_dev: The device the buffer should be attached to
* @buffer: The buffer to attach to the device
*
@@ -1744,8 +1769,13 @@ EXPORT_SYMBOL_GPL(iio_buffer_put);
void iio_device_attach_buffer(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
- indio_dev->buffer = iio_buffer_get(buffer);
+ buffer = iio_buffer_get(buffer);
+ buffer->indio_dev = indio_dev;
+
+ /* keep this for legacy */
+ if (!indio_dev->buffer)
+ indio_dev->buffer = buffer;

- indio_dev->buffer->indio_dev = indio_dev;
+ list_add_tail(&buffer->attached_entry, &indio_dev->attached_buffers);
}
EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index b27fabf13e9c..067e5de76b6c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1534,6 +1534,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
}
dev_set_name(&dev->dev, "iio:device%d", dev->id);
INIT_LIST_HEAD(&dev->buffer_list);
+ INIT_LIST_HEAD(&dev->attached_buffers);
INIT_LIST_HEAD(&dev->ioctl_handlers);

return dev;
diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h
index e8203b6d51a1..9ee3a7c0a657 100644
--- a/include/linux/iio/buffer_impl.h
+++ b/include/linux/iio/buffer_impl.h
@@ -130,6 +130,9 @@ struct iio_buffer {
/* @demux_bounce: Buffer for doing gather from incoming scan. */
void *demux_bounce;

+ /* @attached_buffers: Entry in the devices list of attached buffers. */
+ 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.h b/include/linux/iio/iio.h
index 671f5818fa67..32ba1a303454 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -492,6 +492,7 @@ struct iio_buffer_setup_ops {
* @event_interface: [INTERN] event chrdevs associated with interrupt lines
* @buffer: [DRIVER] any buffer present
* @buffer_list: [INTERN] list of all buffers currently attached
+ * @attached_buffers: [INTERN] list of all attached buffers
* @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux
* @mlock: [INTERN] lock used to prevent simultaneous device state
* changes
@@ -536,6 +537,7 @@ struct iio_dev {

struct iio_buffer *buffer;
struct list_head buffer_list;
+ struct list_head attached_buffers;
int scan_bytes;
struct mutex mlock;

--
2.17.1

2020-05-08 13:57:14

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 09/14] iio: buffer: split buffer sysfs creation to take buffer as primary arg

Currently the iio_buffer_{alloc,free}_sysfs_and_mask() take 'indio_dev' as
primary argument. This change converts to take an IIO buffer as a primary
argument.

That will allow the functions to get called for multiple buffers.

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

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index e7a847e7b103..6b1b5d5387bd 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1312,26 +1312,14 @@ static struct attribute *iio_buffer_attrs[] = {
&dev_attr_data_available.attr,
};

-int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
+static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
{
+ struct iio_dev *indio_dev = buffer->indio_dev;
struct iio_dev_attr *p;
struct attribute **attr;
- struct iio_buffer *buffer = indio_dev->buffer;
int ret, i, attrn, attrcount, attrcount_orig = 0;
const struct iio_chan_spec *channels;

- channels = indio_dev->channels;
- if (channels) {
- int ml = indio_dev->masklength;
-
- for (i = 0; i < indio_dev->num_channels; i++)
- ml = max(ml, channels[i].scan_index + 1);
- indio_dev->masklength = ml;
- }
-
- if (!buffer)
- return 0;
-
attrcount = 0;
if (buffer->attrs) {
while (buffer->attrs[attrcount] != NULL)
@@ -1411,19 +1399,45 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
return ret;
}

-void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
+int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer = indio_dev->buffer;
+ const struct iio_chan_spec *channels;
+ int i;
+
+ channels = indio_dev->channels;
+ if (channels) {
+ int ml = indio_dev->masklength;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ ml = max(ml, channels[i].scan_index + 1);
+ indio_dev->masklength = ml;
+ }

if (!buffer)
- return;
+ return 0;
+
+ return __iio_buffer_alloc_sysfs_and_mask(buffer);
+}

+static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
+{
iio_buffer_free_scanmask(buffer);
kfree(buffer->buffer_group.attrs);
kfree(buffer->scan_el_group.attrs);
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
}

+void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ if (!buffer)
+ return;
+
+ __iio_buffer_free_sysfs_and_mask(buffer);
+}
+
static const struct file_operations iio_buffer_fileops = {
.read = iio_buffer_read_outer,
.release = iio_buffer_chrdev_release,
--
2.17.1

2020-05-08 13:57:42

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 04/14] iio: core,buffer: wrap iio_buffer_put() call into iio_buffers_put()

The name (and the wrapper) seems superfluous now, but when more buffers
will be attached to the IIO device this will be a bit more useful.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/iio_core.h | 4 ++++
drivers/iio/industrialio-buffer.c | 10 ++++++++++
drivers/iio/industrialio-core.c | 2 +-
3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index fd9a5f1d5e51..39ec0344fb68 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -51,6 +51,8 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev);
#define iio_buffer_poll_addr (&iio_buffer_poll)
#define iio_buffer_read_outer_addr (&iio_buffer_read_outer)

+void iio_device_buffers_put(struct iio_dev *indio_dev);
+
void iio_disable_all_buffers(struct iio_dev *indio_dev);
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);

@@ -66,6 +68,8 @@ static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)

static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {}

+static inline void iio_device_buffers_put(struct iio_dev *indio_dev) {}
+
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 3b1071deba00..93f187455461 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1371,6 +1371,16 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
}

+void iio_device_buffers_put(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ if (!buffer)
+ return;
+
+ iio_buffer_put(buffer);
+}
+
/**
* iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
* @indio_dev: the iio device
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 462d3e810013..32c489139cd2 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1481,7 +1481,7 @@ static void iio_dev_release(struct device *device)
iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev);

- iio_buffer_put(indio_dev->buffer);
+ iio_device_buffers_put(indio_dev);

ida_simple_remove(&iio_ida, indio_dev->id);
kfree(indio_dev);
--
2.17.1

2020-05-08 13:58:14

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 05/14] iio: core: register chardev only if needed

The final intent is to localize all buffer ops into the
industrialio-buffer.c file, to be able to add support for multiple buffers
per IIO device.

We only need a chardev if we need to support buffers and/or events.

With this change, a chardev will be created only if an IIO buffer is
attached OR an event_interface is configured.

Otherwise, no chardev will be created, and the IIO device will get
registered with the 'device_add()' call.

Quite a lot of IIO devices don't really need a chardev, so this is a minor
improvement to the IIO core, as the IIO device will take up (slightly)
fewer resources.

What's important to remember, is that removing a chardev also requires that
'indio_dev->dev.devt' to be initialized. If it is, a '/dev/iio:deviceX'
file will be created by the kernel, regardless of whether it has a chardev
attached to it or not.
If that field is not initialized, cdev_device_{add,del}() behave{s} like
device_{add,del}().

Also, since we plan to add more chardevs for IIO buffers, we need to
consider now a separate IDA object just for chardevs.
Currently, the only benefit is that chardev IDs will be continuous.
However, when adding a chardev per IIO buffer, the IDs for the chardev
could outpace the IDs for IIO devices, so these should be decoupled.

Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-core.c | 58 +++++++++++++++++++++++++++++----
1 file changed, 51 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 32c489139cd2..d74279efeca4 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -35,6 +35,9 @@
/* IDA to assign each registered device a unique id */
static DEFINE_IDA(iio_ida);

+/* IDA to assign each registered character device a unique id */
+static DEFINE_IDA(iio_chrdev_ida);
+
static dev_t iio_devt;

#define IIO_DEV_MAX 256
@@ -1680,8 +1683,40 @@ static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
return 0;
}

+static int iio_device_alloc_chrdev_id(struct device *dev)
+{
+ int id;
+
+ id = ida_simple_get(&iio_chrdev_ida, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ /* cannot use a dev_err as the name isn't available */
+ dev_err(dev, "failed to get device id\n");
+ return id;
+ }
+
+ dev->devt = MKDEV(MAJOR(iio_devt), id);
+
+ return 0;
+}
+
+static void iio_device_free_chrdev_id(struct device *dev)
+{
+ if (!dev->devt)
+ return;
+ ida_simple_remove(&iio_chrdev_ida, MINOR(dev->devt));
+}
+
static const struct iio_buffer_setup_ops noop_ring_setup_ops;

+static const struct file_operations iio_event_fileops = {
+ .owner = THIS_MODULE,
+ .llseek = noop_llseek,
+ .unlocked_ioctl = iio_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
+ .open = iio_chrdev_open,
+ .release = iio_chrdev_release,
+};
+
int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
{
int ret;
@@ -1701,9 +1736,6 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
if (ret < 0)
return ret;

- /* configure elements for the chrdev */
- indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
-
iio_device_register_debugfs(indio_dev);

ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
@@ -1732,16 +1764,27 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
indio_dev->setup_ops == NULL)
indio_dev->setup_ops = &noop_ring_setup_ops;

- cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
+ if (indio_dev->buffer)
+ cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
+ else if (indio_dev->event_interface)
+ cdev_init(&indio_dev->chrdev, &iio_event_fileops);

- indio_dev->chrdev.owner = this_mod;
+ if (indio_dev->buffer || indio_dev->event_interface) {
+ indio_dev->chrdev.owner = this_mod;
+
+ ret = iio_device_alloc_chrdev_id(&indio_dev->dev);
+ if (ret)
+ goto error_unreg_eventset;
+ }

ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
- if (ret < 0)
- goto error_unreg_eventset;
+ if (ret)
+ goto error_free_chrdev_id;

return 0;

+error_free_chrdev_id:
+ iio_device_free_chrdev_id(&indio_dev->dev);
error_unreg_eventset:
iio_device_unregister_eventset(indio_dev);
error_free_sysfs:
@@ -1761,6 +1804,7 @@ EXPORT_SYMBOL(__iio_device_register);
void iio_device_unregister(struct iio_dev *indio_dev)
{
cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
+ iio_device_free_chrdev_id(&indio_dev->dev);

mutex_lock(&indio_dev->info_exist_lock);

--
2.17.1

2020-05-08 13:58:15

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 01/14] iio: Move scan mask management to the core

From: Lars-Peter Clausen <[email protected]>

Let the core handle the buffer scan mask management including allocation
and channel selection. Having this handled in a central place rather than
open-coding it all over the place will make it easier to change the
implementation.

Signed-off-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/buffer/industrialio-buffer-cb.c | 16 ++++-----
drivers/iio/industrialio-buffer.c | 36 +++++++++++++++------
drivers/iio/inkern.c | 15 +++++++++
include/linux/iio/consumer.h | 10 ++++++
4 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c
index 47c96f7f4976..3db389ea3f4e 100644
--- a/drivers/iio/buffer/industrialio-buffer-cb.c
+++ b/drivers/iio/buffer/industrialio-buffer-cb.c
@@ -34,7 +34,7 @@ static void iio_buffer_cb_release(struct iio_buffer *buffer)
{
struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);

- bitmap_free(cb_buff->buffer.scan_mask);
+ iio_buffer_free_scanmask(&cb_buff->buffer);
kfree(cb_buff);
}

@@ -72,27 +72,25 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
}

cb_buff->indio_dev = cb_buff->channels[0].indio_dev;
- cb_buff->buffer.scan_mask = bitmap_zalloc(cb_buff->indio_dev->masklength,
- GFP_KERNEL);
- if (cb_buff->buffer.scan_mask == NULL) {
- ret = -ENOMEM;
+
+ ret = iio_buffer_alloc_scanmask(&cb_buff->buffer, cb_buff->indio_dev);
+ if (ret)
goto error_release_channels;
- }
+
chan = &cb_buff->channels[0];
while (chan->indio_dev) {
if (chan->indio_dev != cb_buff->indio_dev) {
ret = -EINVAL;
goto error_free_scan_mask;
}
- set_bit(chan->channel->scan_index,
- cb_buff->buffer.scan_mask);
+ iio_buffer_channel_enable(&cb_buff->buffer, chan);
chan++;
}

return cb_buff;

error_free_scan_mask:
- bitmap_free(cb_buff->buffer.scan_mask);
+ iio_buffer_free_scanmask(&cb_buff->buffer);
error_release_channels:
iio_channel_release_all(cb_buff->channels);
error_free_cb_buff:
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index eae39eaf49af..7eed97c1df14 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -208,6 +208,26 @@ void iio_buffer_init(struct iio_buffer *buffer)
}
EXPORT_SYMBOL(iio_buffer_init);

+int iio_buffer_alloc_scanmask(struct iio_buffer *buffer,
+ struct iio_dev *indio_dev)
+{
+ if (!indio_dev->masklength)
+ return -EINVAL;
+
+ buffer->scan_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
+ if (buffer->scan_mask == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iio_buffer_alloc_scanmask);
+
+void iio_buffer_free_scanmask(struct iio_buffer *buffer)
+{
+ bitmap_free(buffer->scan_mask);
+}
+EXPORT_SYMBOL_GPL(iio_buffer_free_scanmask);
+
/**
* iio_buffer_set_attrs - Set buffer specific attributes
* @buffer: The buffer for which we are setting attributes
@@ -1306,14 +1326,10 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
indio_dev->scan_index_timestamp =
channels[i].scan_index;
}
- if (indio_dev->masklength && buffer->scan_mask == NULL) {
- buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
- GFP_KERNEL);
- if (buffer->scan_mask == NULL) {
- ret = -ENOMEM;
- goto error_cleanup_dynamic;
- }
- }
+
+ ret = iio_buffer_alloc_scanmask(buffer, indio_dev);
+ if (ret)
+ goto error_cleanup_dynamic;
}

buffer->scan_el_group.name = iio_scan_elements_group_name;
@@ -1334,7 +1350,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
return 0;

error_free_scan_mask:
- bitmap_free(buffer->scan_mask);
+ iio_buffer_free_scanmask(buffer);
error_cleanup_dynamic:
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
kfree(buffer->buffer_group.attrs);
@@ -1349,7 +1365,7 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
if (!buffer)
return;

- bitmap_free(buffer->scan_mask);
+ iio_buffer_free_scanmask(buffer);
kfree(buffer->buffer_group.attrs);
kfree(buffer->scan_el_group.attrs);
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index ede99e0d5371..f35cb9985edc 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -11,6 +11,7 @@

#include <linux/iio/iio.h>
#include "iio_core.h"
+#include <linux/iio/buffer_impl.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/iio/consumer.h>
@@ -857,6 +858,20 @@ int iio_write_channel_raw(struct iio_channel *chan, int val)
}
EXPORT_SYMBOL_GPL(iio_write_channel_raw);

+void iio_buffer_channel_enable(struct iio_buffer *buffer,
+ const struct iio_channel *chan)
+{
+ set_bit(chan->channel->scan_index, buffer->scan_mask);
+}
+EXPORT_SYMBOL_GPL(iio_buffer_channel_enable);
+
+void iio_buffer_channel_disable(struct iio_buffer *buffer,
+ const struct iio_channel *chan)
+{
+ clear_bit(chan->channel->scan_index, buffer->scan_mask);
+}
+EXPORT_SYMBOL_GPL(iio_buffer_channel_disable);
+
unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
{
const struct iio_chan_spec_ext_info *ext_info;
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index c4118dcb8e05..dbc87c26250a 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -12,6 +12,7 @@

struct iio_dev;
struct iio_chan_spec;
+struct iio_buffer;
struct device;

/**
@@ -342,6 +343,15 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val,
int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
int *processed, unsigned int scale);

+void iio_buffer_channel_enable(struct iio_buffer *buffer,
+ const struct iio_channel *chan);
+void iio_buffer_channel_disable(struct iio_buffer *buffer,
+ const struct iio_channel *chan);
+
+int iio_buffer_alloc_scanmask(struct iio_buffer *buffer,
+ struct iio_dev *indio_dev);
+void iio_buffer_free_scanmask(struct iio_buffer *buffer);
+
/**
* iio_get_channel_ext_info_count() - get number of ext_info attributes
* connected to the channel.
--
2.17.1

2020-05-08 13:59:32

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 02/14] iio: hw_consumer: use new scanmask functions

From: Lars-Peter Clausen <[email protected]>

This change moves the handling of the scanmasks to the new wrapper
functions that were added in a previous commit.

Signed-off-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/buffer/industrialio-hw-consumer.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
index f2d27788f666..f1cc72520685 100644
--- a/drivers/iio/buffer/industrialio-hw-consumer.c
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -28,7 +28,6 @@ struct hw_consumer_buffer {
struct list_head head;
struct iio_dev *indio_dev;
struct iio_buffer buffer;
- long scan_mask[];
};

static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer(
@@ -41,6 +40,8 @@ static void iio_hw_buf_release(struct iio_buffer *buffer)
{
struct hw_consumer_buffer *hw_buf =
iio_buffer_to_hw_consumer_buffer(buffer);
+
+ iio_buffer_free_scanmask(buffer);
kfree(hw_buf);
}

@@ -52,26 +53,34 @@ static const struct iio_buffer_access_funcs iio_hw_buf_access = {
static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
struct iio_hw_consumer *hwc, struct iio_dev *indio_dev)
{
- size_t mask_size = BITS_TO_LONGS(indio_dev->masklength) * sizeof(long);
struct hw_consumer_buffer *buf;
+ int ret;

list_for_each_entry(buf, &hwc->buffers, head) {
if (buf->indio_dev == indio_dev)
return buf;
}

- buf = kzalloc(sizeof(*buf) + mask_size, GFP_KERNEL);
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
return NULL;

buf->buffer.access = &iio_hw_buf_access;
buf->indio_dev = indio_dev;
- buf->buffer.scan_mask = buf->scan_mask;

iio_buffer_init(&buf->buffer);
+
+ ret = iio_buffer_alloc_scanmask(&buf->buffer, indio_dev);
+ if (ret)
+ goto err_free_buf;
+
list_add_tail(&buf->head, &hwc->buffers);

return buf;
+
+err_free_buf:
+ kfree(buf);
+ return NULL;
}

/**
@@ -106,7 +115,7 @@ struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
ret = -ENOMEM;
goto err_put_buffers;
}
- set_bit(chan->channel->scan_index, buf->buffer.scan_mask);
+ iio_buffer_channel_enable(&buf->buffer, chan);
chan++;
}

--
2.17.1

2020-05-08 14:00:12

by Alexandru Ardelean

[permalink] [raw]
Subject: [RFC PATCH 03/14] iio: buffer: add back-ref from iio_buffer to iio_dev

An IIO device will have multiple buffers, but it shouldn't be allowed that
an IIO buffer should belong to more than 1 IIO device.

Once things get moved more from IIO device to the IIO buffer, and an IIO
device will be able to have more than 1 buffer attached, there will be a
need for a back-ref to the IIO device [from the IIO buffer].

This change adds that.

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

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 7eed97c1df14..3b1071deba00 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1493,5 +1493,7 @@ void iio_device_attach_buffer(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
indio_dev->buffer = iio_buffer_get(buffer);
+
+ indio_dev->buffer->indio_dev = indio_dev;
}
EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h
index a63dc07b7350..67d73d465e02 100644
--- a/include/linux/iio/buffer_impl.h
+++ b/include/linux/iio/buffer_impl.h
@@ -69,6 +69,9 @@ struct iio_buffer_access_funcs {
* those writing new buffer implementations.
*/
struct iio_buffer {
+ /** @indio_dev: IIO device to which this buffer belongs to. */
+ struct iio_dev *indio_dev;
+
/** @length: Number of datums in buffer. */
unsigned int length;

--
2.17.1

2020-05-09 08:54:06

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> [...]
> What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> This is because the 'buffer->dev.parent = &indio_dev->dev'.
> But I do feel this is correct.
> So, now I don't know whether to leave it like that or symlink to shorter
> versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
> mostly to make the names unique. It would have looked weird to do
> '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
>
> So, now I'm thinking of whether all this is acceptable.
> Or what is acceptable?
> Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
> What else should I consider moving forward?
> What means forward?
> Where did I leave my beer?

Looking at how the /dev/ devices are named I think we can provide a name
that is different from the dev_name() of the device. Have a look at
device_get_devnode() in drivers/base/core.c. We should be able to
provide the name for the chardev through the devnode() callback.

While we are at this, do we want to move the new devices into an iio
subfolder? So iio/buffer0:0 instead of iio:buffer0:0?

2020-05-10 10:11:55

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Sat, 9 May 2020 10:52:14 +0200
Lars-Peter Clausen <[email protected]> wrote:

> On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > [...]
> > What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > But I do feel this is correct.
> > So, now I don't know whether to leave it like that or symlink to shorter
> > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
> > mostly to make the names unique. It would have looked weird to do
> > '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
> >
> > So, now I'm thinking of whether all this is acceptable.
> > Or what is acceptable?
> > Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
> > What else should I consider moving forward?
> > What means forward?
> > Where did I leave my beer?
>
> Looking at how the /dev/ devices are named I think we can provide a name
> that is different from the dev_name() of the device. Have a look at
> device_get_devnode() in drivers/base/core.c. We should be able to
> provide the name for the chardev through the devnode() callback.
>
> While we are at this, do we want to move the new devices into an iio
> subfolder? So iio/buffer0:0 instead of iio:buffer0:0?

Possibly on the folder. I can't for the life of me remember why I decided
not to do that the first time around - I'll leave it at the
mysterious "it may turn out to be harder than you'd think..."
Hopefully not ;)

Do we want to make the naming a bit more self describing, something like
iio/device0:buffer0? Given the legacy interface will be outside
the directory anyway, could even do

iio/device0/buffer0 with link to iio:device0
iio/device0/buffer1 with no legacy link.

Ah, the bikeshedding fun we have ahead of us!

I think this set is going to take too much thinking for a Sunday
so may take me a little while to do a proper review...
+ I have a few other side projects I want to hammer on today :)

Jonathan

2020-05-11 10:36:08

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> [External]
>
> On Sat, 9 May 2020 10:52:14 +0200
> Lars-Peter Clausen <[email protected]> wrote:
>
> > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > [...]
> > > What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> > > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > > But I do feel this is correct.
> > > So, now I don't know whether to leave it like that or symlink to shorter
> > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
> > > mostly to make the names unique. It would have looked weird to do
> > > '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
> > >
> > > So, now I'm thinking of whether all this is acceptable.
> > > Or what is acceptable?
> > > Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
> > > What else should I consider moving forward?
> > > What means forward?
> > > Where did I leave my beer?
> >
> > Looking at how the /dev/ devices are named I think we can provide a name
> > that is different from the dev_name() of the device. Have a look at
> > device_get_devnode() in drivers/base/core.c. We should be able to
> > provide the name for the chardev through the devnode() callback.
> >
> > While we are at this, do we want to move the new devices into an iio
> > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
>
> Possibly on the folder. I can't for the life of me remember why I decided
> not to do that the first time around - I'll leave it at the
> mysterious "it may turn out to be harder than you'd think..."
> Hopefully not ;)

I was also thinking about the /dev/iio subfolder while doing this.
I can copy that from /dev/input
They seem to do it already.
I don't know how difficult it would be. But it looks like a good precedent.

My concern regarding going to use stuff from core [like device_get_devnode()] is
that it seems to bypass some layers of kernel.
If I do 'git grep device_get_devnode', I get:

drivers/base/core.c: name = device_get_devnode(dev, &mode, &uid,
&gid, &tmp);
drivers/base/core.c: * device_get_devnode - path of device node file
drivers/base/core.c:const char *device_get_devnode(struct device *dev,
drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, &req.mode,
&req.uid, &req.gid, &tmp);
drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, NULL, NULL,
NULL, &tmp);
include/linux/device.h:extern const char *device_get_devnode(struct device *dev,
(END)

So, basically, most uses of device_get_devnode() are in core code, and I feel
that this may be sanctioned somewhere by some core people, if I do it.
I could be wrong, but if you disagree, I'll take your word for it.

I tried using devtmpfs_create_node() directly, and it worked, but again, doing
'git grep devtmpfs_create_node'

drivers/base/base.h:int devtmpfs_create_node(struct device *dev);
drivers/base/base.h:static inline int devtmpfs_create_node(struct device *dev) {
return 0; }
drivers/base/core.c: devtmpfs_create_node(dev);
drivers/base/devtmpfs.c:int devtmpfs_create_node(struct device *dev)
drivers/s390/char/hmcdrv_dev.c: * See: devtmpfs.c, function
devtmpfs_create_node()

Most calls are in core, and the one in hmcdrv driver isn't convincing enough to
do it.
In fact, some may consider it dangerous as it allows drivers/frameworks to use
it as precedent to do more name manipulation.
Again, if you guys say that this would be acceptable, I can use
device_get_devnode() and other stuff from core.


>
> Do we want to make the naming a bit more self describing, something like
> iio/device0:buffer0? Given the legacy interface will be outside
> the directory anyway, could even do
>
> iio/device0/buffer0 with link to iio:device0
> iio/device0/buffer1 with no legacy link.
>
> Ah, the bikeshedding fun we have ahead of us!

This may also depend on how much code it takes to implement these many levels of
folder hierarchy.

>
> I think this set is going to take too much thinking for a Sunday
> so may take me a little while to do a proper review...
> + I have a few other side projects I want to hammer on today :)
>
> Jonathan
>

2020-05-11 10:40:16

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
>> [External]
>>
>> On Sat, 9 May 2020 10:52:14 +0200
>> Lars-Peter Clausen <[email protected]> wrote:
>>
>>> On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
>>>> [...]
>>>> What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
>>>> This is because the 'buffer->dev.parent = &indio_dev->dev'.
>>>> But I do feel this is correct.
>>>> So, now I don't know whether to leave it like that or symlink to shorter
>>>> versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
>>>> The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
>>>> mostly to make the names unique. It would have looked weird to do
>>>> '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
>>>>
>>>> So, now I'm thinking of whether all this is acceptable.
>>>> Or what is acceptable?
>>>> Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
>>>> What else should I consider moving forward?
>>>> What means forward?
>>>> Where did I leave my beer?
>>> Looking at how the /dev/ devices are named I think we can provide a name
>>> that is different from the dev_name() of the device. Have a look at
>>> device_get_devnode() in drivers/base/core.c. We should be able to
>>> provide the name for the chardev through the devnode() callback.
>>>
>>> While we are at this, do we want to move the new devices into an iio
>>> subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
>> Possibly on the folder. I can't for the life of me remember why I decided
>> not to do that the first time around - I'll leave it at the
>> mysterious "it may turn out to be harder than you'd think..."
>> Hopefully not ;)
> I was also thinking about the /dev/iio subfolder while doing this.
> I can copy that from /dev/input
> They seem to do it already.
> I don't know how difficult it would be. But it looks like a good precedent.

All you have to do is return "iio/..." from the devnode() callback.

>
> My concern regarding going to use stuff from core [like device_get_devnode()] is
> that it seems to bypass some layers of kernel.
> If I do 'git grep device_get_devnode', I get:
>
> drivers/base/core.c: name = device_get_devnode(dev, &mode, &uid,
> &gid, &tmp);
> drivers/base/core.c: * device_get_devnode - path of device node file
> drivers/base/core.c:const char *device_get_devnode(struct device *dev,
> drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, &req.mode,
> &req.uid, &req.gid, &tmp);
> drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, NULL, NULL,
> NULL, &tmp);
> include/linux/device.h:extern const char *device_get_devnode(struct device *dev,
> (END)
>
> So, basically, most uses of device_get_devnode() are in core code, and I feel
> that this may be sanctioned somewhere by some core people, if I do it.
> I could be wrong, but if you disagree, I'll take your word for it.
You are not supposed to use the function itself, you should implement
the devnode() callback for the IIO bus, which is then used by the core
device_get_devnode() function.

2020-05-11 13:07:12

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> [External]
>
> On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > [External]
> > >
> > > On Sat, 9 May 2020 10:52:14 +0200
> > > Lars-Peter Clausen <[email protected]> wrote:
> > >
> > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > [...]
> > > > > What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> > > > > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > > > > But I do feel this is correct.
> > > > > So, now I don't know whether to leave it like that or symlink to
> > > > > shorter
> > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
> > > > > mostly to make the names unique. It would have looked weird to do
> > > > > '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
> > > > >
> > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > Or what is acceptable?
> > > > > Should I symlink 'iio:device3/iio:buffer3:0' -> 'iio:device3/buffer0'?
> > > > > What else should I consider moving forward?
> > > > > What means forward?
> > > > > Where did I leave my beer?
> > > > Looking at how the /dev/ devices are named I think we can provide a name
> > > > that is different from the dev_name() of the device. Have a look at
> > > > device_get_devnode() in drivers/base/core.c. We should be able to
> > > > provide the name for the chardev through the devnode() callback.
> > > >
> > > > While we are at this, do we want to move the new devices into an iio
> > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > Possibly on the folder. I can't for the life of me remember why I decided
> > > not to do that the first time around - I'll leave it at the
> > > mysterious "it may turn out to be harder than you'd think..."
> > > Hopefully not ;)
> > I was also thinking about the /dev/iio subfolder while doing this.
> > I can copy that from /dev/input
> > They seem to do it already.
> > I don't know how difficult it would be. But it looks like a good precedent.
>
> All you have to do is return "iio/..." from the devnode() callback.

I admit I did not look closely into drivers/input/input.c before mentioning this
as as good precedent.

But, I looks like /dev/inpput is a class.
While IIO devices are a bus_type devices.
Should we start implementing an IIO class? or?


>
> > My concern regarding going to use stuff from core [like
> > device_get_devnode()] is
> > that it seems to bypass some layers of kernel.
> > If I do 'git grep device_get_devnode', I get:
> >
> > drivers/base/core.c: name = device_get_devnode(dev, &mode, &uid,
> > &gid, &tmp);
> > drivers/base/core.c: * device_get_devnode - path of device node file
> > drivers/base/core.c:const char *device_get_devnode(struct device *dev,
> > drivers/base/devtmpfs.c: req.name = device_get_devnode(dev,
> > &req.mode,
> > &req.uid, &req.gid, &tmp);
> > drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, NULL,
> > NULL,
> > NULL, &tmp);
> > include/linux/device.h:extern const char *device_get_devnode(struct device
> > *dev,
> > (END)
> >
> > So, basically, most uses of device_get_devnode() are in core code, and I
> > feel
> > that this may be sanctioned somewhere by some core people, if I do it.
> > I could be wrong, but if you disagree, I'll take your word for it.
> You are not supposed to use the function itself, you should implement
> the devnode() callback for the IIO bus, which is then used by the core
> device_get_devnode() function.
>

2020-05-11 13:27:02

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> [External]
>
> On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > [External]
> >
> > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > [External]
> > > >
> > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > Lars-Peter Clausen <[email protected]> wrote:
> > > >
> > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > [...]
> > > > > > What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> > > > > > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > > > > > But I do feel this is correct.
> > > > > > So, now I don't know whether to leave it like that or symlink to
> > > > > > shorter
> > > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > > The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
> > > > > > mostly to make the names unique. It would have looked weird to do
> > > > > > '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
> > > > > >
> > > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > > Or what is acceptable?
> > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > 'iio:device3/buffer0'?
> > > > > > What else should I consider moving forward?
> > > > > > What means forward?
> > > > > > Where did I leave my beer?
> > > > > Looking at how the /dev/ devices are named I think we can provide a
> > > > > name
> > > > > that is different from the dev_name() of the device. Have a look at
> > > > > device_get_devnode() in drivers/base/core.c. We should be able to
> > > > > provide the name for the chardev through the devnode() callback.
> > > > >
> > > > > While we are at this, do we want to move the new devices into an iio
> > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > Possibly on the folder. I can't for the life of me remember why I
> > > > decided
> > > > not to do that the first time around - I'll leave it at the
> > > > mysterious "it may turn out to be harder than you'd think..."
> > > > Hopefully not ;)
> > > I was also thinking about the /dev/iio subfolder while doing this.
> > > I can copy that from /dev/input
> > > They seem to do it already.
> > > I don't know how difficult it would be. But it looks like a good
> > > precedent.
> >
> > All you have to do is return "iio/..." from the devnode() callback.
>
> I admit I did not look closely into drivers/input/input.c before mentioning
> this
> as as good precedent.
>
> But, I looks like /dev/inpput is a class.
> While IIO devices are a bus_type devices.
> Should we start implementing an IIO class? or?

What I should have highlighted [before] with this, is that there is no devnode()
callback for the bus_type [type].

>
>
> > > My concern regarding going to use stuff from core [like
> > > device_get_devnode()] is
> > > that it seems to bypass some layers of kernel.
> > > If I do 'git grep device_get_devnode', I get:
> > >
> > > drivers/base/core.c: name = device_get_devnode(dev, &mode,
> > > &uid,
> > > &gid, &tmp);
> > > drivers/base/core.c: * device_get_devnode - path of device node file
> > > drivers/base/core.c:const char *device_get_devnode(struct device *dev,
> > > drivers/base/devtmpfs.c: req.name = device_get_devnode(dev,
> > > &req.mode,
> > > &req.uid, &req.gid, &tmp);
> > > drivers/base/devtmpfs.c: req.name = device_get_devnode(dev, NULL,
> > > NULL,
> > > NULL, &tmp);
> > > include/linux/device.h:extern const char *device_get_devnode(struct device
> > > *dev,
> > > (END)
> > >
> > > So, basically, most uses of device_get_devnode() are in core code, and I
> > > feel
> > > that this may be sanctioned somewhere by some core people, if I do it.
> > > I could be wrong, but if you disagree, I'll take your word for it.
> > You are not supposed to use the function itself, you should implement
> > the devnode() callback for the IIO bus, which is then used by the core
> > device_get_devnode() function.
> >

2020-05-11 13:59:53

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
>> [External]
>>
>> On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
>>> [External]
>>>
>>> On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
>>>> On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
>>>>> [External]
>>>>>
>>>>> On Sat, 9 May 2020 10:52:14 +0200
>>>>> Lars-Peter Clausen <[email protected]> wrote:
>>>>>
>>>>>> On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
>>>>>>> [...]
>>>>>>> What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
>>>>>>> This is because the 'buffer->dev.parent = &indio_dev->dev'.
>>>>>>> But I do feel this is correct.
>>>>>>> So, now I don't know whether to leave it like that or symlink to
>>>>>>> shorter
>>>>>>> versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
>>>>>>> The reason for naming the IIO buffer devices to 'iio:bufferX:Y' is
>>>>>>> mostly to make the names unique. It would have looked weird to do
>>>>>>> '/dev/buffer1' if I would have named the buffer devices 'bufferX'.
>>>>>>>
>>>>>>> So, now I'm thinking of whether all this is acceptable.
>>>>>>> Or what is acceptable?
>>>>>>> Should I symlink 'iio:device3/iio:buffer3:0' ->
>>>>>>> 'iio:device3/buffer0'?
>>>>>>> What else should I consider moving forward?
>>>>>>> What means forward?
>>>>>>> Where did I leave my beer?
>>>>>> Looking at how the /dev/ devices are named I think we can provide a
>>>>>> name
>>>>>> that is different from the dev_name() of the device. Have a look at
>>>>>> device_get_devnode() in drivers/base/core.c. We should be able to
>>>>>> provide the name for the chardev through the devnode() callback.
>>>>>>
>>>>>> While we are at this, do we want to move the new devices into an iio
>>>>>> subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
>>>>> Possibly on the folder. I can't for the life of me remember why I
>>>>> decided
>>>>> not to do that the first time around - I'll leave it at the
>>>>> mysterious "it may turn out to be harder than you'd think..."
>>>>> Hopefully not ;)
>>>> I was also thinking about the /dev/iio subfolder while doing this.
>>>> I can copy that from /dev/input
>>>> They seem to do it already.
>>>> I don't know how difficult it would be. But it looks like a good
>>>> precedent.
>>> All you have to do is return "iio/..." from the devnode() callback.
>> I admit I did not look closely into drivers/input/input.c before mentioning
>> this
>> as as good precedent.
>>
>> But, I looks like /dev/inpput is a class.
>> While IIO devices are a bus_type devices.
>> Should we start implementing an IIO class? or?
> What I should have highlighted [before] with this, is that there is no devnode()
> callback for the bus_type [type].
But there is one in device_type :)

2020-05-11 14:59:25

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> [External]
>
> On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > [External]
> > >
> > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > [External]
> > > >
> > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > [External]
> > > > > >
> > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > >
> > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > [...]
> > > > > > > > What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
> > > > > > > > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > > > > > > > But I do feel this is correct.
> > > > > > > > So, now I don't know whether to leave it like that or symlink to
> > > > > > > > shorter
> > > > > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > > > > The reason for naming the IIO buffer devices to 'iio:bufferX:Y'
> > > > > > > > is
> > > > > > > > mostly to make the names unique. It would have looked weird to
> > > > > > > > do
> > > > > > > > '/dev/buffer1' if I would have named the buffer devices
> > > > > > > > 'bufferX'.
> > > > > > > >
> > > > > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > > > > Or what is acceptable?
> > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > What else should I consider moving forward?
> > > > > > > > What means forward?
> > > > > > > > Where did I leave my beer?
> > > > > > > Looking at how the /dev/ devices are named I think we can provide
> > > > > > > a
> > > > > > > name
> > > > > > > that is different from the dev_name() of the device. Have a look
> > > > > > > at
> > > > > > > device_get_devnode() in drivers/base/core.c. We should be able to
> > > > > > > provide the name for the chardev through the devnode() callback.
> > > > > > >
> > > > > > > While we are at this, do we want to move the new devices into an
> > > > > > > iio
> > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > Possibly on the folder. I can't for the life of me remember why I
> > > > > > decided
> > > > > > not to do that the first time around - I'll leave it at the
> > > > > > mysterious "it may turn out to be harder than you'd think..."
> > > > > > Hopefully not ;)
> > > > > I was also thinking about the /dev/iio subfolder while doing this.
> > > > > I can copy that from /dev/input
> > > > > They seem to do it already.
> > > > > I don't know how difficult it would be. But it looks like a good
> > > > > precedent.
> > > > All you have to do is return "iio/..." from the devnode() callback.
> > > I admit I did not look closely into drivers/input/input.c before
> > > mentioning
> > > this
> > > as as good precedent.
> > >
> > > But, I looks like /dev/inpput is a class.
> > > While IIO devices are a bus_type devices.
> > > Should we start implementing an IIO class? or?
> > What I should have highlighted [before] with this, is that there is no
> > devnode()
> > callback for the bus_type [type].
> But there is one in device_type :)

Many thanks :)
That worked nicely.

I now have:

root@analog:~# ls /dev/iio/*
/dev/iio/iio:device0 /dev/iio/iio:device1

/dev/iio/device3:
buffer0 buffer1 buffer2 buffer3

/dev/iio/device4:
buffer0


It looks like I can shift these around as needed.
This is just an experiment.
I managed to move the iio devices under /dev/iio, though probably the IIO
devices will still be around as /dev/iio:deviceX for legacy reasons.

Two things remain unresolved.
1. The name of the IIO buffer device.

root@analog:/sys/bus/iio/devices# ls iio\:device3/
buffer in_voltage0_test_mode name
events in_voltage1_test_mode of_node
iio:buffer:3:0 in_voltage_sampling_frequency power
iio:buffer:3:1 in_voltage_scale scan_elements
iio:buffer:3:2 in_voltage_scale_available subsystem
iio:buffer:3:3 in_voltage_test_mode_available uevent


Right now, each buffer device is named 'iio:buffer:X:Y'.
One suggesttion was 'iio:deviceX:bufferY'
I'm suspecting the latter is preferred as when you sort the folders, buffers
come right after the iio:deviceX folders in /sys/bus/iio/devices.

I don't feel it matters much the device name of the IIO buffer if we symlink it
to a shorter form.

I'm guessing, we symlink these devices to short-hand 'bufferY' folders in each
'iio:deviceX'?

So, you'd get something like:

drwxr-xr-x 8 root root 0 May 11 14:40 .
drwxr-xr-x 4 root root 0 May 11 14:35 ..
lrwxrwxrwx 1 root root 0 May 11 14:35 buffer -> iio:buffer:3:0
lrwxrwxrwx 4 root root 0 May 11 14:35 buffer0 -> iio:buffer:3:0
lrwxrwxrwx 4 root root 0 May 11 14:35 buffer1 -> iio:buffer:3:1
lrwxrwxrwx 4 root root 0 May 11 14:35 buffer2 -> iio:buffer:3:2
lrwxrwxrwx 4 root root 0 May 11 14:35 buffer3 -> iio:buffer:3:3
drwxrwxrwx 2 root root 0 May 11 14:35 events
drwxrwxrwx 4 root root 0 May 11 14:35 iio:buffer:3:0
drwxrwxrwx 4 root root 0 May 11 14:35 iio:buffer:3:1
drwxrwxrwx 4 root root 0 May 11 14:35 iio:buffer:3:2
drwxrwxrwx 4 root root 0 May 11 14:35 iio:buffer:3:3
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage0_test_mode
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage1_test_mode
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage_sampling_frequency
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage_scale
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage_scale_available
-rw-rw-rw- 1 root root 4096 May 11 14:35 in_voltage_test_mode_available
-rw-rw-rw- 1 root root 4096 May 11 14:35 name
lrwxrwxrwx 1 root root 0 May 11 14:35 of_node ->
../../../../../firmware/devicetree/base/fpga-axi@0/axi-ad9680-hpc@44a10000
drwxrwxrwx 2 root root 0 May 11 14:35 power
lrwxrwxrwx 1 root root 0 May 11 14:35 scan_elements ->
iio:buffer:3:0/scan_elements
lrwxrwxrwx 1 root root 0 May 11 14:35 subsystem -> ../../../../../bus/iio
-rw-rw-rw- 1 root root 4096 May 11 14:35 uevent

1a. /sys/bus/iio/devices looks like this:
iio:buffer:3:0 (this would become iio:device3:buffer0 )
iio:buffer:3:1
iio:buffer
:3:2
iio:buffer:3:3
iio:buffer:4:0
iio:device0
iio:device1
iio:device2
iio:device3
iio:
device4

One minor issue here is that the buffers get listed in the /sys/bus/iio/devices
folder, because I'm adding them to the iio bus, to be able to get a chardev
[from the pre-allocated chardev region of IIO].

libiio gets a little confused, as it sees these buffers are IIO buffer capable
devices;

iio:buffer:3:0: (buffer capable)
2 channels found:
voltage0: (input, index: 0, format: le:S14/16>>0)
voltage1: (input, index: 1, format: le:S14/16>>0)
5 device-specific attributes found:
attr 0: data_available value: 0
attr 1: enable value: 0
attr 2: length value: 4096
attr 3: length_align_bytes value: 8
attr 4: watermark value: 2048
iio:buffer:3:1: (buffer capable)

Hopefully, this is not a big problem, but let's see.

2. I know this is [still] stupid now; but any suggestions one how to symlink
/dev/iio:device3 -> /dev/iio/device3/buffer0 ?

Regarding this one, I may try a few things, but any suggestion is welcome.



Thanks
Alex

2020-05-11 19:59:19

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
>> [External]
>>
>> On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
>>> On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
>>>> [External]
>>>>
>>>> On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
>>>>> [External]
>>>>>
>>>>> On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
>>>>>> On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
>>>>>>> [External]
>>>>>>>
>>>>>>> On Sat, 9 May 2020 10:52:14 +0200
>>>>>>> Lars-Peter Clausen <[email protected]> wrote:
>>>>>>>
>>>>>>>> On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
>>>>>>>>> [...]
>>>>>>>>> What I don't like, is that iio:device3 has iio:buffer3:0 (to 3).
>>>>>>>>> This is because the 'buffer->dev.parent = &indio_dev->dev'.
>>>>>>>>> But I do feel this is correct.
>>>>>>>>> So, now I don't know whether to leave it like that or symlink to
>>>>>>>>> shorter
>>>>>>>>> versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
>>>>>>>>> The reason for naming the IIO buffer devices to 'iio:bufferX:Y'
>>>>>>>>> is
>>>>>>>>> mostly to make the names unique. It would have looked weird to
>>>>>>>>> do
>>>>>>>>> '/dev/buffer1' if I would have named the buffer devices
>>>>>>>>> 'bufferX'.
>>>>>>>>>
>>>>>>>>> So, now I'm thinking of whether all this is acceptable.
>>>>>>>>> Or what is acceptable?
>>>>>>>>> Should I symlink 'iio:device3/iio:buffer3:0' ->
>>>>>>>>> 'iio:device3/buffer0'?
>>>>>>>>> What else should I consider moving forward?
>>>>>>>>> What means forward?
>>>>>>>>> Where did I leave my beer?
>>>>>>>> Looking at how the /dev/ devices are named I think we can provide
>>>>>>>> a
>>>>>>>> name
>>>>>>>> that is different from the dev_name() of the device. Have a look
>>>>>>>> at
>>>>>>>> device_get_devnode() in drivers/base/core.c. We should be able to
>>>>>>>> provide the name for the chardev through the devnode() callback.
>>>>>>>>
>>>>>>>> While we are at this, do we want to move the new devices into an
>>>>>>>> iio
>>>>>>>> subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
>>>>>>> Possibly on the folder. I can't for the life of me remember why I
>>>>>>> decided
>>>>>>> not to do that the first time around - I'll leave it at the
>>>>>>> mysterious "it may turn out to be harder than you'd think..."
>>>>>>> Hopefully not ;)
>>>>>> I was also thinking about the /dev/iio subfolder while doing this.
>>>>>> I can copy that from /dev/input
>>>>>> They seem to do it already.
>>>>>> I don't know how difficult it would be. But it looks like a good
>>>>>> precedent.
>>>>> All you have to do is return "iio/..." from the devnode() callback.
>>>> I admit I did not look closely into drivers/input/input.c before
>>>> mentioning
>>>> this
>>>> as as good precedent.
>>>>
>>>> But, I looks like /dev/inpput is a class.
>>>> While IIO devices are a bus_type devices.
>>>> Should we start implementing an IIO class? or?
>>> What I should have highlighted [before] with this, is that there is no
>>> devnode()
>>> callback for the bus_type [type].
>> But there is one in device_type :)
> Many thanks :)
> That worked nicely.
>
> I now have:
>
> root@analog:~# ls /dev/iio/*
> /dev/iio/iio:device0 /dev/iio/iio:device1
>
> /dev/iio/device3:
> buffer0 buffer1 buffer2 buffer3
>
> /dev/iio/device4:
> buffer0
>
>
> It looks like I can shift these around as needed.
> This is just an experiment.
> I managed to move the iio devices under /dev/iio, though probably the IIO
> devices will still be around as /dev/iio:deviceX for legacy reasons.
>
> Two things remain unresolved.
> 1. The name of the IIO buffer device.
>
> root@analog:/sys/bus/iio/devices# ls iio\:device3/
> buffer in_voltage0_test_mode name
> events in_voltage1_test_mode of_node
> iio:buffer:3:0 in_voltage_sampling_frequency power
> iio:buffer:3:1 in_voltage_scale scan_elements
> iio:buffer:3:2 in_voltage_scale_available subsystem
> iio:buffer:3:3 in_voltage_test_mode_available uevent
>
>
> Right now, each buffer device is named 'iio:buffer:X:Y'.
> One suggesttion was 'iio:deviceX:bufferY'
> I'm suspecting the latter is preferred as when you sort the folders, buffers
> come right after the iio:deviceX folders in /sys/bus/iio/devices.
>
> I don't feel it matters much the device name of the IIO buffer if we symlink it
> to a shorter form.
>
> I'm guessing, we symlink these devices to short-hand 'bufferY' folders in each
> 'iio:deviceX'?

I think that would be a bit excessive. Only for the legacy buffer we
need to have a symlink.

> [...]
> 2. I know this is [still] stupid now; but any suggestions one how to symlink
> /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
>
Does not seem to be possible. Userspace will have to take care of it.
This means we need to keep legacy devices in /dev/ and only new buffers
in /dev/iio/.


2020-05-12 06:29:00

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Mon, 2020-05-11 at 21:56 +0200, Lars-Peter Clausen wrote:
> [External]
>
> On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> > On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> > > [External]
> > >
> > > On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > > > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > > > [External]
> > > > >
> > > > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > > > [External]
> > > > > >
> > > > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > > > [External]
> > > > > > > >
> > > > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > > > >
> > > > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > > > [...]
> > > > > > > > > > What I don't like, is that iio:device3 has iio:buffer3:0 (to
> > > > > > > > > > 3).
> > > > > > > > > > This is because the 'buffer->dev.parent = &indio_dev->dev'.
> > > > > > > > > > But I do feel this is correct.
> > > > > > > > > > So, now I don't know whether to leave it like that or
> > > > > > > > > > symlink to
> > > > > > > > > > shorter
> > > > > > > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > > > > > > The reason for naming the IIO buffer devices to
> > > > > > > > > > 'iio:bufferX:Y'
> > > > > > > > > > is
> > > > > > > > > > mostly to make the names unique. It would have looked weird
> > > > > > > > > > to
> > > > > > > > > > do
> > > > > > > > > > '/dev/buffer1' if I would have named the buffer devices
> > > > > > > > > > 'bufferX'.
> > > > > > > > > >
> > > > > > > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > > > > > > Or what is acceptable?
> > > > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > > > What else should I consider moving forward?
> > > > > > > > > > What means forward?
> > > > > > > > > > Where did I leave my beer?
> > > > > > > > > Looking at how the /dev/ devices are named I think we can
> > > > > > > > > provide
> > > > > > > > > a
> > > > > > > > > name
> > > > > > > > > that is different from the dev_name() of the device. Have a
> > > > > > > > > look
> > > > > > > > > at
> > > > > > > > > device_get_devnode() in drivers/base/core.c. We should be able
> > > > > > > > > to
> > > > > > > > > provide the name for the chardev through the devnode()
> > > > > > > > > callback.
> > > > > > > > >
> > > > > > > > > While we are at this, do we want to move the new devices into
> > > > > > > > > an
> > > > > > > > > iio
> > > > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > > > Possibly on the folder. I can't for the life of me remember why
> > > > > > > > I
> > > > > > > > decided
> > > > > > > > not to do that the first time around - I'll leave it at the
> > > > > > > > mysterious "it may turn out to be harder than you'd think..."
> > > > > > > > Hopefully not ;)
> > > > > > > I was also thinking about the /dev/iio subfolder while doing this.
> > > > > > > I can copy that from /dev/input
> > > > > > > They seem to do it already.
> > > > > > > I don't know how difficult it would be. But it looks like a good
> > > > > > > precedent.
> > > > > > All you have to do is return "iio/..." from the devnode() callback.
> > > > > I admit I did not look closely into drivers/input/input.c before
> > > > > mentioning
> > > > > this
> > > > > as as good precedent.
> > > > >
> > > > > But, I looks like /dev/inpput is a class.
> > > > > While IIO devices are a bus_type devices.
> > > > > Should we start implementing an IIO class? or?
> > > > What I should have highlighted [before] with this, is that there is no
> > > > devnode()
> > > > callback for the bus_type [type].
> > > But there is one in device_type :)
> > Many thanks :)
> > That worked nicely.
> >
> > I now have:
> >
> > root@analog:~# ls /dev/iio/*
> > /dev/iio/iio:device0 /dev/iio/iio:device1
> >
> > /dev/iio/device3:
> > buffer0 buffer1 buffer2 buffer3
> >
> > /dev/iio/device4:
> > buffer0
> >
> >
> > It looks like I can shift these around as needed.
> > This is just an experiment.
> > I managed to move the iio devices under /dev/iio, though probably the IIO
> > devices will still be around as /dev/iio:deviceX for legacy reasons.
> >
> > Two things remain unresolved.
> > 1. The name of the IIO buffer device.
> >
> > root@analog:/sys/bus/iio/devices# ls iio\:device3/
> > buffer in_voltage0_test_mode name
> > events in_voltage1_test_mode of_node
> > iio:buffer:3:0 in_voltage_sampling_frequency power
> > iio:buffer:3:1 in_voltage_scale scan_elements
> > iio:buffer:3:2 in_voltage_scale_available subsystem
> > iio:buffer:3:3 in_voltage_test_mode_available uevent
> >
> >
> > Right now, each buffer device is named 'iio:buffer:X:Y'.
> > One suggesttion was 'iio:deviceX:bufferY'
> > I'm suspecting the latter is preferred as when you sort the folders, buffers
> > come right after the iio:deviceX folders in /sys/bus/iio/devices.
> >
> > I don't feel it matters much the device name of the IIO buffer if we symlink
> > it
> > to a shorter form.
> >
> > I'm guessing, we symlink these devices to short-hand 'bufferY' folders in
> > each
> > 'iio:deviceX'?
>
> I think that would be a bit excessive. Only for the legacy buffer we
> need to have a symlink.
>
> > [...]
> > 2. I know this is [still] stupid now; but any suggestions one how to symlink
> > /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
> >
> Does not seem to be possible. Userspace will have to take care of it.
> This means we need to keep legacy devices in /dev/ and only new buffers
> in /dev/iio/.

One thought about this, was that we keep the chardev for the IIO device for
this.
i.e. /dev/iio:deviceX and /dev/iio/deviceX/buffer0 open the same buffer.
This means that for a device with 4 buffers, you get 5 chardevs.
This also seems a bit much/excessive. Maybe also in terms of source-code.
It would at least mean not moving the event-only chardev to 'industrialio-
event.c', OR move it, and have the same chardev in 3 places ['industrialio-
event.c', 'industrialio-buffer.c' & 'industrialio-buffer.c'

Maybe this sort-of makes sense to have for a few years/kernel-revisions until
things clean-up.

I guess at this point, the maintainer should have the final say about this.

>
>

2020-05-16 13:10:54

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Tue, 2020-05-12 at 06:26 +0000, Ardelean, Alexandru wrote:
> [External]
>
> On Mon, 2020-05-11 at 21:56 +0200, Lars-Peter Clausen wrote:
> > [External]
> >
> > On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> > > On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> > > > [External]
> > > >
> > > > On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > > > > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > > > > [External]
> > > > > >
> > > > > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > > > > [External]
> > > > > > >
> > > > > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > > > > [External]
> > > > > > > > >
> > > > > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > > > > >
> > > > > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > > > > [...]
> > > > > > > > > > > What I don't like, is that iio:device3 has iio:buffer3:0
> > > > > > > > > > > (to
> > > > > > > > > > > 3).
> > > > > > > > > > > This is because the 'buffer->dev.parent = &indio_dev-
> > > > > > > > > > > >dev'.
> > > > > > > > > > > But I do feel this is correct.
> > > > > > > > > > > So, now I don't know whether to leave it like that or
> > > > > > > > > > > symlink to
> > > > > > > > > > > shorter
> > > > > > > > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > > > > > > > The reason for naming the IIO buffer devices to
> > > > > > > > > > > 'iio:bufferX:Y'
> > > > > > > > > > > is
> > > > > > > > > > > mostly to make the names unique. It would have looked
> > > > > > > > > > > weird
> > > > > > > > > > > to
> > > > > > > > > > > do
> > > > > > > > > > > '/dev/buffer1' if I would have named the buffer devices
> > > > > > > > > > > 'bufferX'.
> > > > > > > > > > >
> > > > > > > > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > > > > > > > Or what is acceptable?
> > > > > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > > > > What else should I consider moving forward?
> > > > > > > > > > > What means forward?
> > > > > > > > > > > Where did I leave my beer?
> > > > > > > > > > Looking at how the /dev/ devices are named I think we can
> > > > > > > > > > provide
> > > > > > > > > > a
> > > > > > > > > > name
> > > > > > > > > > that is different from the dev_name() of the device. Have a
> > > > > > > > > > look
> > > > > > > > > > at
> > > > > > > > > > device_get_devnode() in drivers/base/core.c. We should be
> > > > > > > > > > able
> > > > > > > > > > to
> > > > > > > > > > provide the name for the chardev through the devnode()
> > > > > > > > > > callback.
> > > > > > > > > >
> > > > > > > > > > While we are at this, do we want to move the new devices
> > > > > > > > > > into
> > > > > > > > > > an
> > > > > > > > > > iio
> > > > > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > > > > Possibly on the folder. I can't for the life of me remember
> > > > > > > > > why
> > > > > > > > > I
> > > > > > > > > decided
> > > > > > > > > not to do that the first time around - I'll leave it at the
> > > > > > > > > mysterious "it may turn out to be harder than you'd think..."
> > > > > > > > > Hopefully not ;)
> > > > > > > > I was also thinking about the /dev/iio subfolder while doing
> > > > > > > > this.
> > > > > > > > I can copy that from /dev/input
> > > > > > > > They seem to do it already.
> > > > > > > > I don't know how difficult it would be. But it looks like a good
> > > > > > > > precedent.
> > > > > > > All you have to do is return "iio/..." from the devnode()
> > > > > > > callback.
> > > > > > I admit I did not look closely into drivers/input/input.c before
> > > > > > mentioning
> > > > > > this
> > > > > > as as good precedent.
> > > > > >
> > > > > > But, I looks like /dev/inpput is a class.
> > > > > > While IIO devices are a bus_type devices.
> > > > > > Should we start implementing an IIO class? or?
> > > > > What I should have highlighted [before] with this, is that there is no
> > > > > devnode()
> > > > > callback for the bus_type [type].
> > > > But there is one in device_type :)
> > > Many thanks :)
> > > That worked nicely.
> > >
> > > I now have:
> > >
> > > root@analog:~# ls /dev/iio/*
> > > /dev/iio/iio:device0 /dev/iio/iio:device1
> > >
> > > /dev/iio/device3:
> > > buffer0 buffer1 buffer2 buffer3
> > >
> > > /dev/iio/device4:
> > > buffer0
> > >
> > >
> > > It looks like I can shift these around as needed.
> > > This is just an experiment.
> > > I managed to move the iio devices under /dev/iio, though probably the IIO
> > > devices will still be around as /dev/iio:deviceX for legacy reasons.
> > >
> > > Two things remain unresolved.
> > > 1. The name of the IIO buffer device.
> > >
> > > root@analog:/sys/bus/iio/devices# ls iio\:device3/
> > > buffer in_voltage0_test_mode name
> > > events in_voltage1_test_mode of_node
> > > iio:buffer:3:0 in_voltage_sampling_frequency power
> > > iio:buffer:3:1 in_voltage_scale scan_elements
> > > iio:buffer:3:2 in_voltage_scale_available subsystem
> > > iio:buffer:3:3 in_voltage_test_mode_available uevent
> > >
> > >
> > > Right now, each buffer device is named 'iio:buffer:X:Y'.
> > > One suggesttion was 'iio:deviceX:bufferY'
> > > I'm suspecting the latter is preferred as when you sort the folders,
> > > buffers
> > > come right after the iio:deviceX folders in /sys/bus/iio/devices.
> > >
> > > I don't feel it matters much the device name of the IIO buffer if we
> > > symlink
> > > it
> > > to a shorter form.
> > >
> > > I'm guessing, we symlink these devices to short-hand 'bufferY' folders in
> > > each
> > > 'iio:deviceX'?
> >
> > I think that would be a bit excessive. Only for the legacy buffer we
> > need to have a symlink.
> >
> > > [...]
> > > 2. I know this is [still] stupid now; but any suggestions one how to
> > > symlink
> > > /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
> > >
> > Does not seem to be possible. Userspace will have to take care of it.
> > This means we need to keep legacy devices in /dev/ and only new buffers
> > in /dev/iio/.
>
> One thought about this, was that we keep the chardev for the IIO device for
> this.
> i.e. /dev/iio:deviceX and /dev/iio/deviceX/buffer0 open the same buffer.
> This means that for a device with 4 buffers, you get 5 chardevs.
> This also seems a bit much/excessive. Maybe also in terms of source-code.
> It would at least mean not moving the event-only chardev to 'industrialio-
> event.c', OR move it, and have the same chardev in 3 places ['industrialio-
> event.c', 'industrialio-buffer.c' & 'industrialio-buffer.c'
>
> Maybe this sort-of makes sense to have for a few years/kernel-revisions until
> things clean-up.
>
> I guess at this point, the maintainer should have the final say about this.

Another 'compromise' idea, is that we make this '/dev/iio/deviceX/bufferY' thing
a feature for new devices, and leave '/dev/iio:deviceX' devices [for buffers] a
thing for current devices.
It would mean adding a 'new' iio_device_attach_buffer(); no idea on a name [for
this yet].

Over time, people can convert existing drivers to the new IIO-buffer format, if
they want to. That also gives them a bit better control over symlinking
'/dev/iio:deviceX' -> '/dev/iio/deviceX/bufferY' [or symlinking in reverse if
they want to].

That may create confusion I guess during a transition period.
And it would [ideally] have a mechanism [preferably at build/compile time] to
notify users to use the new IIO buffer mechanism [vs the old one] when adding
new drivers.
Otherwise, there's the risk of people copying the old IIO buffer mechanism.
This can be brought-up at review, but ¯\_(ツ)_/¯ ; it can be annoying.


>
> >

2020-05-16 16:27:06

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Sat, 16 May 2020 13:08:46 +0000
"Ardelean, Alexandru" <[email protected]> wrote:

> On Tue, 2020-05-12 at 06:26 +0000, Ardelean, Alexandru wrote:
> > [External]
> >
> > On Mon, 2020-05-11 at 21:56 +0200, Lars-Peter Clausen wrote:
> > > [External]
> > >
> > > On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> > > > On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> > > > > [External]
> > > > >
> > > > > On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > > > > > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > > > > > [External]
> > > > > > >
> > > > > > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > > > > > [External]
> > > > > > > >
> > > > > > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > > > > > [External]
> > > > > > > > > >
> > > > > > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > > > > > >
> > > > > > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > > > > > [...]
> > > > > > > > > > > > What I don't like, is that iio:device3 has iio:buffer3:0
> > > > > > > > > > > > (to
> > > > > > > > > > > > 3).
> > > > > > > > > > > > This is because the 'buffer->dev.parent = &indio_dev-
> > > > > > > > > > > > >dev'.
> > > > > > > > > > > > But I do feel this is correct.
> > > > > > > > > > > > So, now I don't know whether to leave it like that or
> > > > > > > > > > > > symlink to
> > > > > > > > > > > > shorter
> > > > > > > > > > > > versions like 'iio:buffer3:Y' -> 'iio:device3/bufferY'.
> > > > > > > > > > > > The reason for naming the IIO buffer devices to
> > > > > > > > > > > > 'iio:bufferX:Y'
> > > > > > > > > > > > is
> > > > > > > > > > > > mostly to make the names unique. It would have looked
> > > > > > > > > > > > weird
> > > > > > > > > > > > to
> > > > > > > > > > > > do
> > > > > > > > > > > > '/dev/buffer1' if I would have named the buffer devices
> > > > > > > > > > > > 'bufferX'.
> > > > > > > > > > > >
> > > > > > > > > > > > So, now I'm thinking of whether all this is acceptable.
> > > > > > > > > > > > Or what is acceptable?
> > > > > > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > > > > > What else should I consider moving forward?
> > > > > > > > > > > > What means forward?
> > > > > > > > > > > > Where did I leave my beer?
> > > > > > > > > > > Looking at how the /dev/ devices are named I think we can
> > > > > > > > > > > provide
> > > > > > > > > > > a
> > > > > > > > > > > name
> > > > > > > > > > > that is different from the dev_name() of the device. Have a
> > > > > > > > > > > look
> > > > > > > > > > > at
> > > > > > > > > > > device_get_devnode() in drivers/base/core.c. We should be
> > > > > > > > > > > able
> > > > > > > > > > > to
> > > > > > > > > > > provide the name for the chardev through the devnode()
> > > > > > > > > > > callback.
> > > > > > > > > > >
> > > > > > > > > > > While we are at this, do we want to move the new devices
> > > > > > > > > > > into
> > > > > > > > > > > an
> > > > > > > > > > > iio
> > > > > > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > > > > > Possibly on the folder. I can't for the life of me remember
> > > > > > > > > > why
> > > > > > > > > > I
> > > > > > > > > > decided
> > > > > > > > > > not to do that the first time around - I'll leave it at the
> > > > > > > > > > mysterious "it may turn out to be harder than you'd think..."
> > > > > > > > > > Hopefully not ;)
> > > > > > > > > I was also thinking about the /dev/iio subfolder while doing
> > > > > > > > > this.
> > > > > > > > > I can copy that from /dev/input
> > > > > > > > > They seem to do it already.
> > > > > > > > > I don't know how difficult it would be. But it looks like a good
> > > > > > > > > precedent.
> > > > > > > > All you have to do is return "iio/..." from the devnode()
> > > > > > > > callback.
> > > > > > > I admit I did not look closely into drivers/input/input.c before
> > > > > > > mentioning
> > > > > > > this
> > > > > > > as as good precedent.
> > > > > > >
> > > > > > > But, I looks like /dev/inpput is a class.
> > > > > > > While IIO devices are a bus_type devices.
> > > > > > > Should we start implementing an IIO class? or?
> > > > > > What I should have highlighted [before] with this, is that there is no
> > > > > > devnode()
> > > > > > callback for the bus_type [type].
> > > > > But there is one in device_type :)
> > > > Many thanks :)
> > > > That worked nicely.
> > > >
> > > > I now have:
> > > >
> > > > root@analog:~# ls /dev/iio/*
> > > > /dev/iio/iio:device0 /dev/iio/iio:device1
> > > >
> > > > /dev/iio/device3:
> > > > buffer0 buffer1 buffer2 buffer3
> > > >
> > > > /dev/iio/device4:
> > > > buffer0
> > > >
> > > >
> > > > It looks like I can shift these around as needed.
> > > > This is just an experiment.
> > > > I managed to move the iio devices under /dev/iio, though probably the IIO
> > > > devices will still be around as /dev/iio:deviceX for legacy reasons.
> > > >
> > > > Two things remain unresolved.
> > > > 1. The name of the IIO buffer device.
> > > >
> > > > root@analog:/sys/bus/iio/devices# ls iio\:device3/
> > > > buffer in_voltage0_test_mode name
> > > > events in_voltage1_test_mode of_node
> > > > iio:buffer:3:0 in_voltage_sampling_frequency power
> > > > iio:buffer:3:1 in_voltage_scale scan_elements
> > > > iio:buffer:3:2 in_voltage_scale_available subsystem
> > > > iio:buffer:3:3 in_voltage_test_mode_available uevent
> > > >
> > > >
> > > > Right now, each buffer device is named 'iio:buffer:X:Y'.
> > > > One suggesttion was 'iio:deviceX:bufferY'
> > > > I'm suspecting the latter is preferred as when you sort the folders,
> > > > buffers
> > > > come right after the iio:deviceX folders in /sys/bus/iio/devices.
> > > >
> > > > I don't feel it matters much the device name of the IIO buffer if we
> > > > symlink
> > > > it
> > > > to a shorter form.
> > > >
> > > > I'm guessing, we symlink these devices to short-hand 'bufferY' folders in
> > > > each
> > > > 'iio:deviceX'?
> > >
> > > I think that would be a bit excessive. Only for the legacy buffer we
> > > need to have a symlink.
> > >
> > > > [...]
> > > > 2. I know this is [still] stupid now; but any suggestions one how to
> > > > symlink
> > > > /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
> > > >
> > > Does not seem to be possible. Userspace will have to take care of it.
> > > This means we need to keep legacy devices in /dev/ and only new buffers
> > > in /dev/iio/.
> >
> > One thought about this, was that we keep the chardev for the IIO device for
> > this.
> > i.e. /dev/iio:deviceX and /dev/iio/deviceX/buffer0 open the same buffer.
> > This means that for a device with 4 buffers, you get 5 chardevs.
> > This also seems a bit much/excessive. Maybe also in terms of source-code.
> > It would at least mean not moving the event-only chardev to 'industrialio-
> > event.c', OR move it, and have the same chardev in 3 places ['industrialio-
> > event.c', 'industrialio-buffer.c' & 'industrialio-buffer.c'
> >
> > Maybe this sort-of makes sense to have for a few years/kernel-revisions until
> > things clean-up.
> >
> > I guess at this point, the maintainer should have the final say about this.
>
> Another 'compromise' idea, is that we make this '/dev/iio/deviceX/bufferY' thing
> a feature for new devices, and leave '/dev/iio:deviceX' devices [for buffers] a
> thing for current devices.
> It would mean adding a 'new' iio_device_attach_buffer(); no idea on a name [for
> this yet].

Definitely a no to that. If we make this transition it needs to be
automatic and subsystem wide. At some point we could have a kconfig option
to disable the legacy interface subsystem wise as a precursor to eventually
dropping it.

>
> Over time, people can convert existing drivers to the new IIO-buffer format, if
> they want to. That also gives them a bit better control over symlinking
> '/dev/iio:deviceX' -> '/dev/iio/deviceX/bufferY' [or symlinking in reverse if
> they want to].
>
> That may create confusion I guess during a transition period.
> And it would [ideally] have a mechanism [preferably at build/compile time] to
> notify users to use the new IIO buffer mechanism [vs the old one] when adding
> new drivers.
> Otherwise, there's the risk of people copying the old IIO buffer mechanism.
> This can be brought-up at review, but ¯\_(ツ)_/¯ ; it can be annoying.

If we can't do this in a transparent fashion we need to rethink.
The existing interface 'has' to remain and do something sensible. Realistically
we need to keep it in place for 3-5 years at least.

I'm not yet convinced the complexity is worthwhile. We 'could' fallback to
the same trick used for events and use an ioctl to access all buffers
other than the first one... Then we retain one chardev per iio device
and still get the flexibility we need to have multiple buffers.
In some ways it is tidier, even if a bit less intuitive...
If we can't build the symlinks we were all kind of assuming we could
we may need to rethink the overall path.

Anyhow, you are doing great work exploring the options!

Thanks,

Jonathan


>
>
> >
> > >

2020-05-17 06:28:17

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Sat, 2020-05-16 at 17:24 +0100, Jonathan Cameron wrote:
> [External]
>
> On Sat, 16 May 2020 13:08:46 +0000
> "Ardelean, Alexandru" <[email protected]> wrote:
>
> > On Tue, 2020-05-12 at 06:26 +0000, Ardelean, Alexandru wrote:
> > > [External]
> > >
> > > On Mon, 2020-05-11 at 21:56 +0200, Lars-Peter Clausen wrote:
> > > > [External]
> > > >
> > > > On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> > > > > On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> > > > > > [External]
> > > > > >
> > > > > > On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > > > > > > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > > > > > > [External]
> > > > > > > >
> > > > > > > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > > > > > > [External]
> > > > > > > > >
> > > > > > > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > > > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > > > > > > [External]
> > > > > > > > > > >
> > > > > > > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > > > > > > >
> > > > > > > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > > > > > > [...]
> > > > > > > > > > > > > What I don't like, is that iio:device3 has
> > > > > > > > > > > > > iio:buffer3:0
> > > > > > > > > > > > > (to
> > > > > > > > > > > > > 3).
> > > > > > > > > > > > > This is because the 'buffer->dev.parent =
> > > > > > > > > > > > > &indio_dev-
> > > > > > > > > > > > > > dev'.
> > > > > > > > > > > > > But I do feel this is correct.
> > > > > > > > > > > > > So, now I don't know whether to leave it like that or
> > > > > > > > > > > > > symlink to
> > > > > > > > > > > > > shorter
> > > > > > > > > > > > > versions like 'iio:buffer3:Y' ->
> > > > > > > > > > > > > 'iio:device3/bufferY'.
> > > > > > > > > > > > > The reason for naming the IIO buffer devices to
> > > > > > > > > > > > > 'iio:bufferX:Y'
> > > > > > > > > > > > > is
> > > > > > > > > > > > > mostly to make the names unique. It would have looked
> > > > > > > > > > > > > weird
> > > > > > > > > > > > > to
> > > > > > > > > > > > > do
> > > > > > > > > > > > > '/dev/buffer1' if I would have named the buffer
> > > > > > > > > > > > > devices
> > > > > > > > > > > > > 'bufferX'.
> > > > > > > > > > > > >
> > > > > > > > > > > > > So, now I'm thinking of whether all this is
> > > > > > > > > > > > > acceptable.
> > > > > > > > > > > > > Or what is acceptable?
> > > > > > > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > > > > > > What else should I consider moving forward?
> > > > > > > > > > > > > What means forward?
> > > > > > > > > > > > > Where did I leave my beer?
> > > > > > > > > > > > Looking at how the /dev/ devices are named I think we
> > > > > > > > > > > > can
> > > > > > > > > > > > provide
> > > > > > > > > > > > a
> > > > > > > > > > > > name
> > > > > > > > > > > > that is different from the dev_name() of the device.
> > > > > > > > > > > > Have a
> > > > > > > > > > > > look
> > > > > > > > > > > > at
> > > > > > > > > > > > device_get_devnode() in drivers/base/core.c. We should
> > > > > > > > > > > > be
> > > > > > > > > > > > able
> > > > > > > > > > > > to
> > > > > > > > > > > > provide the name for the chardev through the devnode()
> > > > > > > > > > > > callback.
> > > > > > > > > > > >
> > > > > > > > > > > > While we are at this, do we want to move the new devices
> > > > > > > > > > > > into
> > > > > > > > > > > > an
> > > > > > > > > > > > iio
> > > > > > > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > > > > > > Possibly on the folder. I can't for the life of me
> > > > > > > > > > > remember
> > > > > > > > > > > why
> > > > > > > > > > > I
> > > > > > > > > > > decided
> > > > > > > > > > > not to do that the first time around - I'll leave it at
> > > > > > > > > > > the
> > > > > > > > > > > mysterious "it may turn out to be harder than you'd
> > > > > > > > > > > think..."
> > > > > > > > > > > Hopefully not ;)
> > > > > > > > > > I was also thinking about the /dev/iio subfolder while doing
> > > > > > > > > > this.
> > > > > > > > > > I can copy that from /dev/input
> > > > > > > > > > They seem to do it already.
> > > > > > > > > > I don't know how difficult it would be. But it looks like a
> > > > > > > > > > good
> > > > > > > > > > precedent.
> > > > > > > > > All you have to do is return "iio/..." from the devnode()
> > > > > > > > > callback.
> > > > > > > > I admit I did not look closely into drivers/input/input.c before
> > > > > > > > mentioning
> > > > > > > > this
> > > > > > > > as as good precedent.
> > > > > > > >
> > > > > > > > But, I looks like /dev/inpput is a class.
> > > > > > > > While IIO devices are a bus_type devices.
> > > > > > > > Should we start implementing an IIO class? or?
> > > > > > > What I should have highlighted [before] with this, is that there
> > > > > > > is no
> > > > > > > devnode()
> > > > > > > callback for the bus_type [type].
> > > > > > But there is one in device_type :)
> > > > > Many thanks :)
> > > > > That worked nicely.
> > > > >
> > > > > I now have:
> > > > >
> > > > > root@analog:~# ls /dev/iio/*
> > > > > /dev/iio/iio:device0 /dev/iio/iio:device1
> > > > >
> > > > > /dev/iio/device3:
> > > > > buffer0 buffer1 buffer2 buffer3
> > > > >
> > > > > /dev/iio/device4:
> > > > > buffer0
> > > > >
> > > > >
> > > > > It looks like I can shift these around as needed.
> > > > > This is just an experiment.
> > > > > I managed to move the iio devices under /dev/iio, though probably the
> > > > > IIO
> > > > > devices will still be around as /dev/iio:deviceX for legacy reasons.
> > > > >
> > > > > Two things remain unresolved.
> > > > > 1. The name of the IIO buffer device.
> > > > >
> > > > > root@analog:/sys/bus/iio/devices# ls iio\:device3/
> > > > > buffer in_voltage0_test_mode name
> > > > > events in_voltage1_test_mode of_node
> > > > > iio:buffer:3:0 in_voltage_sampling_frequency power
> > > > > iio:buffer:3:1 in_voltage_scale scan_elements
> > > > > iio:buffer:3:2 in_voltage_scale_available subsystem
> > > > > iio:buffer:3:3 in_voltage_test_mode_available uevent
> > > > >
> > > > >
> > > > > Right now, each buffer device is named 'iio:buffer:X:Y'.
> > > > > One suggesttion was 'iio:deviceX:bufferY'
> > > > > I'm suspecting the latter is preferred as when you sort the folders,
> > > > > buffers
> > > > > come right after the iio:deviceX folders in /sys/bus/iio/devices.
> > > > >
> > > > > I don't feel it matters much the device name of the IIO buffer if we
> > > > > symlink
> > > > > it
> > > > > to a shorter form.
> > > > >
> > > > > I'm guessing, we symlink these devices to short-hand 'bufferY' folders
> > > > > in
> > > > > each
> > > > > 'iio:deviceX'?
> > > >
> > > > I think that would be a bit excessive. Only for the legacy buffer we
> > > > need to have a symlink.
> > > >
> > > > > [...]
> > > > > 2. I know this is [still] stupid now; but any suggestions one how to
> > > > > symlink
> > > > > /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
> > > > >
> > > > Does not seem to be possible. Userspace will have to take care of it.
> > > > This means we need to keep legacy devices in /dev/ and only new buffers
> > > > in /dev/iio/.
> > >
> > > One thought about this, was that we keep the chardev for the IIO device
> > > for
> > > this.
> > > i.e. /dev/iio:deviceX and /dev/iio/deviceX/buffer0 open the same buffer.
> > > This means that for a device with 4 buffers, you get 5 chardevs.
> > > This also seems a bit much/excessive. Maybe also in terms of source-code.
> > > It would at least mean not moving the event-only chardev to 'industrialio-
> > > event.c', OR move it, and have the same chardev in 3 places
> > > ['industrialio-
> > > event.c', 'industrialio-buffer.c' & 'industrialio-buffer.c'
> > >
> > > Maybe this sort-of makes sense to have for a few years/kernel-revisions
> > > until
> > > things clean-up.
> > >
> > > I guess at this point, the maintainer should have the final say about
> > > this.
> >
> > Another 'compromise' idea, is that we make this '/dev/iio/deviceX/bufferY'
> > thing
> > a feature for new devices, and leave '/dev/iio:deviceX' devices [for
> > buffers] a
> > thing for current devices.
> > It would mean adding a 'new' iio_device_attach_buffer(); no idea on a name
> > [for
> > this yet].
>
> Definitely a no to that. If we make this transition it needs to be
> automatic and subsystem wide. At some point we could have a kconfig option
> to disable the legacy interface subsystem wise as a precursor to eventually
> dropping it.
>
> > Over time, people can convert existing drivers to the new IIO-buffer format,
> > if
> > they want to. That also gives them a bit better control over symlinking
> > '/dev/iio:deviceX' -> '/dev/iio/deviceX/bufferY' [or symlinking in reverse
> > if
> > they want to].
> >
> > That may create confusion I guess during a transition period.
> > And it would [ideally] have a mechanism [preferably at build/compile time]
> > to
> > notify users to use the new IIO buffer mechanism [vs the old one] when
> > adding
> > new drivers.
> > Otherwise, there's the risk of people copying the old IIO buffer mechanism.
> > This can be brought-up at review, but ¯\_(ツ)_/¯ ; it can be annoying.
>
> If we can't do this in a transparent fashion we need to rethink.
> The existing interface 'has' to remain and do something sensible.
> Realistically
> we need to keep it in place for 3-5 years at least.
>
> I'm not yet convinced the complexity is worthwhile. We 'could' fallback to
> the same trick used for events and use an ioctl to access all buffers
> other than the first one... Then we retain one chardev per iio device
> and still get the flexibility we need to have multiple buffers.
> In some ways it is tidier, even if a bit less intuitive...
> If we can't build the symlinks we were all kind of assuming we could
> we may need to rethink the overall path.
>
> Anyhow, you are doing great work exploring the options!

I wonder if you got to read the idea about adding more chardevs.

The one where /dev/iio:deviceX & /dev/iio/deviceX/buffer0 open the same buffer
object. I'm not sure about any race issues here.
The bad-part [I feel] is that we get more duplication on chardev file_operations
(open, release, ioctl, etc).
We need to re-wrap code-paths so that they open the same buffer.
And the number of chardevs per IIO device increases by 1 (for a device with 4
buffers == 4 chardevs + 1 legacy)

I kinda like the idea of the /dev/iio/ folder. But I'm not strongly opinionated
towards it either.
This also allows some /dev/iio/deviceX/eventY chardevs.
And some other types of chardevs /dev/iio/deviceX/somethingNewY

But, if I think about it, the only benefit of this [over anon inodes for
chardevs] is that it allows us to do direct access via cat/echo to the actual
chardev of the buffer.
Then, there's also the fact that adding more chardevs increases complexity to
userspace, so it won't matter much. People would probably prefer some userspace
IIO library to do the data read/write.

I'm getting the feeling now that the final debathe is 'anon inodes or not'

Thoughts here?


>
> Thanks,
>
> Jonathan
>
>
> >
> > >
> > > >

2020-05-17 13:42:42

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 00/14] iio: buffer: add support for multiple buffers

On Sun, 17 May 2020 06:26:17 +0000
"Ardelean, Alexandru" <[email protected]> wrote:

> On Sat, 2020-05-16 at 17:24 +0100, Jonathan Cameron wrote:
> > [External]
> >
> > On Sat, 16 May 2020 13:08:46 +0000
> > "Ardelean, Alexandru" <[email protected]> wrote:
> >
> > > On Tue, 2020-05-12 at 06:26 +0000, Ardelean, Alexandru wrote:
> > > > [External]
> > > >
> > > > On Mon, 2020-05-11 at 21:56 +0200, Lars-Peter Clausen wrote:
> > > > > [External]
> > > > >
> > > > > On 5/11/20 4:56 PM, Ardelean, Alexandru wrote:
> > > > > > On Mon, 2020-05-11 at 15:58 +0200, Lars-Peter Clausen wrote:
> > > > > > > [External]
> > > > > > >
> > > > > > > On 5/11/20 3:24 PM, Ardelean, Alexandru wrote:
> > > > > > > > On Mon, 2020-05-11 at 13:03 +0000, Ardelean, Alexandru wrote:
> > > > > > > > > [External]
> > > > > > > > >
> > > > > > > > > On Mon, 2020-05-11 at 12:37 +0200, Lars-Peter Clausen wrote:
> > > > > > > > > > [External]
> > > > > > > > > >
> > > > > > > > > > On 5/11/20 12:33 PM, Ardelean, Alexandru wrote:
> > > > > > > > > > > On Sun, 2020-05-10 at 11:09 +0100, Jonathan Cameron wrote:
> > > > > > > > > > > > [External]
> > > > > > > > > > > >
> > > > > > > > > > > > On Sat, 9 May 2020 10:52:14 +0200
> > > > > > > > > > > > Lars-Peter Clausen <[email protected]> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > > On 5/8/20 3:53 PM, Alexandru Ardelean wrote:
> > > > > > > > > > > > > > [...]
> > > > > > > > > > > > > > What I don't like, is that iio:device3 has
> > > > > > > > > > > > > > iio:buffer3:0
> > > > > > > > > > > > > > (to
> > > > > > > > > > > > > > 3).
> > > > > > > > > > > > > > This is because the 'buffer->dev.parent =
> > > > > > > > > > > > > > &indio_dev-
> > > > > > > > > > > > > > > dev'.
> > > > > > > > > > > > > > But I do feel this is correct.
> > > > > > > > > > > > > > So, now I don't know whether to leave it like that or
> > > > > > > > > > > > > > symlink to
> > > > > > > > > > > > > > shorter
> > > > > > > > > > > > > > versions like 'iio:buffer3:Y' ->
> > > > > > > > > > > > > > 'iio:device3/bufferY'.
> > > > > > > > > > > > > > The reason for naming the IIO buffer devices to
> > > > > > > > > > > > > > 'iio:bufferX:Y'
> > > > > > > > > > > > > > is
> > > > > > > > > > > > > > mostly to make the names unique. It would have looked
> > > > > > > > > > > > > > weird
> > > > > > > > > > > > > > to
> > > > > > > > > > > > > > do
> > > > > > > > > > > > > > '/dev/buffer1' if I would have named the buffer
> > > > > > > > > > > > > > devices
> > > > > > > > > > > > > > 'bufferX'.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > So, now I'm thinking of whether all this is
> > > > > > > > > > > > > > acceptable.
> > > > > > > > > > > > > > Or what is acceptable?
> > > > > > > > > > > > > > Should I symlink 'iio:device3/iio:buffer3:0' ->
> > > > > > > > > > > > > > 'iio:device3/buffer0'?
> > > > > > > > > > > > > > What else should I consider moving forward?
> > > > > > > > > > > > > > What means forward?
> > > > > > > > > > > > > > Where did I leave my beer?
> > > > > > > > > > > > > Looking at how the /dev/ devices are named I think we
> > > > > > > > > > > > > can
> > > > > > > > > > > > > provide
> > > > > > > > > > > > > a
> > > > > > > > > > > > > name
> > > > > > > > > > > > > that is different from the dev_name() of the device.
> > > > > > > > > > > > > Have a
> > > > > > > > > > > > > look
> > > > > > > > > > > > > at
> > > > > > > > > > > > > device_get_devnode() in drivers/base/core.c. We should
> > > > > > > > > > > > > be
> > > > > > > > > > > > > able
> > > > > > > > > > > > > to
> > > > > > > > > > > > > provide the name for the chardev through the devnode()
> > > > > > > > > > > > > callback.
> > > > > > > > > > > > >
> > > > > > > > > > > > > While we are at this, do we want to move the new devices
> > > > > > > > > > > > > into
> > > > > > > > > > > > > an
> > > > > > > > > > > > > iio
> > > > > > > > > > > > > subfolder? So iio/buffer0:0 instead of iio:buffer0:0?
> > > > > > > > > > > > Possibly on the folder. I can't for the life of me
> > > > > > > > > > > > remember
> > > > > > > > > > > > why
> > > > > > > > > > > > I
> > > > > > > > > > > > decided
> > > > > > > > > > > > not to do that the first time around - I'll leave it at
> > > > > > > > > > > > the
> > > > > > > > > > > > mysterious "it may turn out to be harder than you'd
> > > > > > > > > > > > think..."
> > > > > > > > > > > > Hopefully not ;)
> > > > > > > > > > > I was also thinking about the /dev/iio subfolder while doing
> > > > > > > > > > > this.
> > > > > > > > > > > I can copy that from /dev/input
> > > > > > > > > > > They seem to do it already.
> > > > > > > > > > > I don't know how difficult it would be. But it looks like a
> > > > > > > > > > > good
> > > > > > > > > > > precedent.
> > > > > > > > > > All you have to do is return "iio/..." from the devnode()
> > > > > > > > > > callback.
> > > > > > > > > I admit I did not look closely into drivers/input/input.c before
> > > > > > > > > mentioning
> > > > > > > > > this
> > > > > > > > > as as good precedent.
> > > > > > > > >
> > > > > > > > > But, I looks like /dev/inpput is a class.
> > > > > > > > > While IIO devices are a bus_type devices.
> > > > > > > > > Should we start implementing an IIO class? or?
> > > > > > > > What I should have highlighted [before] with this, is that there
> > > > > > > > is no
> > > > > > > > devnode()
> > > > > > > > callback for the bus_type [type].
> > > > > > > But there is one in device_type :)
> > > > > > Many thanks :)
> > > > > > That worked nicely.
> > > > > >
> > > > > > I now have:
> > > > > >
> > > > > > root@analog:~# ls /dev/iio/*
> > > > > > /dev/iio/iio:device0 /dev/iio/iio:device1
> > > > > >
> > > > > > /dev/iio/device3:
> > > > > > buffer0 buffer1 buffer2 buffer3
> > > > > >
> > > > > > /dev/iio/device4:
> > > > > > buffer0
> > > > > >
> > > > > >
> > > > > > It looks like I can shift these around as needed.
> > > > > > This is just an experiment.
> > > > > > I managed to move the iio devices under /dev/iio, though probably the
> > > > > > IIO
> > > > > > devices will still be around as /dev/iio:deviceX for legacy reasons.
> > > > > >
> > > > > > Two things remain unresolved.
> > > > > > 1. The name of the IIO buffer device.
> > > > > >
> > > > > > root@analog:/sys/bus/iio/devices# ls iio\:device3/
> > > > > > buffer in_voltage0_test_mode name
> > > > > > events in_voltage1_test_mode of_node
> > > > > > iio:buffer:3:0 in_voltage_sampling_frequency power
> > > > > > iio:buffer:3:1 in_voltage_scale scan_elements
> > > > > > iio:buffer:3:2 in_voltage_scale_available subsystem
> > > > > > iio:buffer:3:3 in_voltage_test_mode_available uevent
> > > > > >
> > > > > >
> > > > > > Right now, each buffer device is named 'iio:buffer:X:Y'.
> > > > > > One suggesttion was 'iio:deviceX:bufferY'
> > > > > > I'm suspecting the latter is preferred as when you sort the folders,
> > > > > > buffers
> > > > > > come right after the iio:deviceX folders in /sys/bus/iio/devices.
> > > > > >
> > > > > > I don't feel it matters much the device name of the IIO buffer if we
> > > > > > symlink
> > > > > > it
> > > > > > to a shorter form.
> > > > > >
> > > > > > I'm guessing, we symlink these devices to short-hand 'bufferY' folders
> > > > > > in
> > > > > > each
> > > > > > 'iio:deviceX'?
> > > > >
> > > > > I think that would be a bit excessive. Only for the legacy buffer we
> > > > > need to have a symlink.
> > > > >
> > > > > > [...]
> > > > > > 2. I know this is [still] stupid now; but any suggestions one how to
> > > > > > symlink
> > > > > > /dev/iio:device3 -> /dev/iio/device3/buffer0 ?
> > > > > >
> > > > > Does not seem to be possible. Userspace will have to take care of it.
> > > > > This means we need to keep legacy devices in /dev/ and only new buffers
> > > > > in /dev/iio/.
> > > >
> > > > One thought about this, was that we keep the chardev for the IIO device
> > > > for
> > > > this.
> > > > i.e. /dev/iio:deviceX and /dev/iio/deviceX/buffer0 open the same buffer.
> > > > This means that for a device with 4 buffers, you get 5 chardevs.
> > > > This also seems a bit much/excessive. Maybe also in terms of source-code.
> > > > It would at least mean not moving the event-only chardev to 'industrialio-
> > > > event.c', OR move it, and have the same chardev in 3 places
> > > > ['industrialio-
> > > > event.c', 'industrialio-buffer.c' & 'industrialio-buffer.c'
> > > >
> > > > Maybe this sort-of makes sense to have for a few years/kernel-revisions
> > > > until
> > > > things clean-up.
> > > >
> > > > I guess at this point, the maintainer should have the final say about
> > > > this.
> > >
> > > Another 'compromise' idea, is that we make this '/dev/iio/deviceX/bufferY'
> > > thing
> > > a feature for new devices, and leave '/dev/iio:deviceX' devices [for
> > > buffers] a
> > > thing for current devices.
> > > It would mean adding a 'new' iio_device_attach_buffer(); no idea on a name
> > > [for
> > > this yet].
> >
> > Definitely a no to that. If we make this transition it needs to be
> > automatic and subsystem wide. At some point we could have a kconfig option
> > to disable the legacy interface subsystem wise as a precursor to eventually
> > dropping it.
> >
> > > Over time, people can convert existing drivers to the new IIO-buffer format,
> > > if
> > > they want to. That also gives them a bit better control over symlinking
> > > '/dev/iio:deviceX' -> '/dev/iio/deviceX/bufferY' [or symlinking in reverse
> > > if
> > > they want to].
> > >
> > > That may create confusion I guess during a transition period.
> > > And it would [ideally] have a mechanism [preferably at build/compile time]
> > > to
> > > notify users to use the new IIO buffer mechanism [vs the old one] when
> > > adding
> > > new drivers.
> > > Otherwise, there's the risk of people copying the old IIO buffer mechanism.
> > > This can be brought-up at review, but ¯\_(ツ)_/¯ ; it can be annoying.
> >
> > If we can't do this in a transparent fashion we need to rethink.
> > The existing interface 'has' to remain and do something sensible.
> > Realistically
> > we need to keep it in place for 3-5 years at least.
> >
> > I'm not yet convinced the complexity is worthwhile. We 'could' fallback to
> > the same trick used for events and use an ioctl to access all buffers
> > other than the first one... Then we retain one chardev per iio device
> > and still get the flexibility we need to have multiple buffers.
> > In some ways it is tidier, even if a bit less intuitive...
> > If we can't build the symlinks we were all kind of assuming we could
> > we may need to rethink the overall path.
> >
> > Anyhow, you are doing great work exploring the options!
>
> I wonder if you got to read the idea about adding more chardevs.
>
> The one where /dev/iio:deviceX & /dev/iio/deviceX/buffer0 open the same buffer
> object. I'm not sure about any race issues here.
> The bad-part [I feel] is that we get more duplication on chardev file_operations
> (open, release, ioctl, etc).
> We need to re-wrap code-paths so that they open the same buffer.
> And the number of chardevs per IIO device increases by 1 (for a device with 4
> buffers == 4 chardevs + 1 legacy)

I read that one and it strikes me as a hack. Two interfaces to the same
thing is always a bad idea if we can possibly avoid it. I was happy enough
with a link if that was doable because then they are the same device with
same dev-node etc. Though thinking more on that it will be hard to get
all the relevant links in place.


>
> I kinda like the idea of the /dev/iio/ folder. But I'm not strongly opinionated
> towards it either.
> This also allows some /dev/iio/deviceX/eventY chardevs.
> And some other types of chardevs /dev/iio/deviceX/somethingNewY

That expansion of chrdevs is kind of what worries me. We end up with
more and more of them.

>
> But, if I think about it, the only benefit of this [over anon inodes for
> chardevs] is that it allows us to do direct access via cat/echo to the actual
> chardev of the buffer.
> Then, there's also the fact that adding more chardevs increases complexity to
> userspace, so it won't matter much. People would probably prefer some userspace
> IIO library to do the data read/write.
>
> I'm getting the feeling now that the final debathe is 'anon inodes or not'

Yes, I think that is the big question. Without your work to explore
the options we wouldn't really know what the other options were.

I'm far from sure what the 'right' answer is to this.

So there is another corner case we should think about. What do we
do about the devices that current expose multiple buffers by having multiple
IIO devices? Usually that occurs for devices that can do weird interleaving
in hardware fifos - hence can produce some channels at N times the frequency of
others - or where we have one shared stream with tagged data.

I suspect it's going to be really hard to map those across to the new interface
with any sort of backwards compatibility. They expose complete iio devices
with all the infrastructure that entails. Maybe we just leave them alone?

J

>
> Thoughts here?
>
>
> >
> > Thanks,
> >
> > Jonathan
> >
> >
> > >
> > > >
> > > > >

2020-05-24 16:43:34

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 05/14] iio: core: register chardev only if needed

On Fri, 8 May 2020 16:53:39 +0300
Alexandru Ardelean <[email protected]> wrote:

> The final intent is to localize all buffer ops into the
> industrialio-buffer.c file, to be able to add support for multiple buffers
> per IIO device.
>
> We only need a chardev if we need to support buffers and/or events.
>
> With this change, a chardev will be created only if an IIO buffer is
> attached OR an event_interface is configured.
>
> Otherwise, no chardev will be created, and the IIO device will get
> registered with the 'device_add()' call.
>
> Quite a lot of IIO devices don't really need a chardev, so this is a minor
> improvement to the IIO core, as the IIO device will take up (slightly)
> fewer resources.
>
> What's important to remember, is that removing a chardev also requires that
> 'indio_dev->dev.devt' to be initialized. If it is, a '/dev/iio:deviceX'
> file will be created by the kernel, regardless of whether it has a chardev
> attached to it or not.
> If that field is not initialized, cdev_device_{add,del}() behave{s} like
> device_{add,del}().
>
> Also, since we plan to add more chardevs for IIO buffers, we need to
> consider now a separate IDA object just for chardevs.
> Currently, the only benefit is that chardev IDs will be continuous.
> However, when adding a chardev per IIO buffer, the IDs for the chardev
> could outpace the IDs for IIO devices, so these should be decoupled.

Given we are still discussing the need for more chardevs I guess
we can't look at patches after this one 'yet'. Up until here they
were all fine independent of the rest of the series.

I was wondering if I could pick up the first part as it is useful
whatever path we take with the rest of the series!

Jonathan

>
> Signed-off-by: Alexandru Ardelean <[email protected]>
> ---
> drivers/iio/industrialio-core.c | 58 +++++++++++++++++++++++++++++----
> 1 file changed, 51 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 32c489139cd2..d74279efeca4 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -35,6 +35,9 @@
> /* IDA to assign each registered device a unique id */
> static DEFINE_IDA(iio_ida);
>
> +/* IDA to assign each registered character device a unique id */
> +static DEFINE_IDA(iio_chrdev_ida);
> +
> static dev_t iio_devt;
>
> #define IIO_DEV_MAX 256
> @@ -1680,8 +1683,40 @@ static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
> return 0;
> }
>
> +static int iio_device_alloc_chrdev_id(struct device *dev)
> +{
> + int id;
> +
> + id = ida_simple_get(&iio_chrdev_ida, 0, 0, GFP_KERNEL);
> + if (id < 0) {
> + /* cannot use a dev_err as the name isn't available */
> + dev_err(dev, "failed to get device id\n");
> + return id;
> + }
> +
> + dev->devt = MKDEV(MAJOR(iio_devt), id);
> +
> + return 0;
> +}
> +
> +static void iio_device_free_chrdev_id(struct device *dev)
> +{
> + if (!dev->devt)
> + return;
> + ida_simple_remove(&iio_chrdev_ida, MINOR(dev->devt));
> +}
> +
> static const struct iio_buffer_setup_ops noop_ring_setup_ops;
>
> +static const struct file_operations iio_event_fileops = {
> + .owner = THIS_MODULE,
> + .llseek = noop_llseek,
> + .unlocked_ioctl = iio_ioctl,
> + .compat_ioctl = compat_ptr_ioctl,
> + .open = iio_chrdev_open,
> + .release = iio_chrdev_release,
> +};
> +
> int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
> {
> int ret;
> @@ -1701,9 +1736,6 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
> if (ret < 0)
> return ret;
>
> - /* configure elements for the chrdev */
> - indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
> -
> iio_device_register_debugfs(indio_dev);
>
> ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
> @@ -1732,16 +1764,27 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
> indio_dev->setup_ops == NULL)
> indio_dev->setup_ops = &noop_ring_setup_ops;
>
> - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
> + if (indio_dev->buffer)
> + cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
> + else if (indio_dev->event_interface)
> + cdev_init(&indio_dev->chrdev, &iio_event_fileops);
>
> - indio_dev->chrdev.owner = this_mod;
> + if (indio_dev->buffer || indio_dev->event_interface) {
> + indio_dev->chrdev.owner = this_mod;
> +
> + ret = iio_device_alloc_chrdev_id(&indio_dev->dev);
> + if (ret)
> + goto error_unreg_eventset;
> + }
>
> ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
> - if (ret < 0)
> - goto error_unreg_eventset;
> + if (ret)
> + goto error_free_chrdev_id;
>
> return 0;
>
> +error_free_chrdev_id:
> + iio_device_free_chrdev_id(&indio_dev->dev);
> error_unreg_eventset:
> iio_device_unregister_eventset(indio_dev);
> error_free_sysfs:
> @@ -1761,6 +1804,7 @@ EXPORT_SYMBOL(__iio_device_register);
> void iio_device_unregister(struct iio_dev *indio_dev)
> {
> cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
> + iio_device_free_chrdev_id(&indio_dev->dev);
>
> mutex_lock(&indio_dev->info_exist_lock);
>

2020-05-24 16:50:11

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 08/14] iio: core: use new common ioctl() mechanism

On Fri, 8 May 2020 16:53:42 +0300
Alexandru Ardelean <[email protected]> wrote:

> This change makes use of the new centralized ioctl() mechanism. The event
> interface registers it's ioctl() handler to IIO device.
> Both the buffer & event interface call 'iio_device_ioctl()', which should
> take care of all of indio_dev's ioctl() calls.
>
> Later, we may add per-buffer ioctl() calls, and since each buffer will get
> it's own chardev, the buffer ioctl() handler will need a bit of tweaking
> for the first/legacy buffer (i.e. indio_dev->buffer).

Do we have an ioctls that aren't safe if we just use them on 'any'
buffer? I don't think we do yet, though I guess we may have in the future.


> Also, those per-buffer ioctl() calls will not be registered with this
> mechanism.
>
> Signed-off-by: Alexandru Ardelean <[email protected]>
> ---
> drivers/iio/iio_core.h | 3 ---
> drivers/iio/industrialio-buffer.c | 2 +-
> drivers/iio/industrialio-event.c | 14 ++++++++------
> 3 files changed, 9 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
> index 34c3e19229d8..f68de4af2738 100644
> --- a/drivers/iio/iio_core.h
> +++ b/drivers/iio/iio_core.h
> @@ -54,9 +54,6 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
> #ifdef CONFIG_IIO_BUFFER
> struct poll_table_struct;
>
> -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> - unsigned int cmd, unsigned long arg);
> -
> void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev);
>
> int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index 1400688f5e42..e7a847e7b103 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -1199,7 +1199,7 @@ static long iio_buffer_ioctl(struct file *filep, unsigned int cmd,
> if (!buffer || !buffer->access)
> return -ENODEV;
>
> - return iio_device_event_ioctl(buffer->indio_dev, filep, cmd, arg);
> + return iio_device_ioctl(buffer->indio_dev, filep, cmd, arg);
> }
>
> static ssize_t iio_buffer_store_enable(struct device *dev,
> diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
> index 0674b2117c98..1961c1d19370 100644
> --- a/drivers/iio/industrialio-event.c
> +++ b/drivers/iio/industrialio-event.c
> @@ -32,6 +32,7 @@
> * @read_lock: lock to protect kfifo read operations
> * @chrdev: associated chardev for this event
> * @indio_dev: IIO device to which this event interface belongs to
> + * @ioctl_handler: handler for event ioctl() calls
> */
> struct iio_event_interface {
> wait_queue_head_t wait;
> @@ -44,6 +45,7 @@ struct iio_event_interface {
>
> struct cdev chrdev;
> struct iio_dev *indio_dev;
> + struct iio_ioctl_handler ioctl_handler;
> };
>
> bool iio_event_enabled(const struct iio_event_interface *ev_int)
> @@ -261,15 +263,12 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp)
> return 0;
> }
>
> -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> +static long iio_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> unsigned int cmd, unsigned long arg)
> {
> int __user *ip = (int __user *)arg;
> int fd;
>
> - if (!indio_dev->info)
> - return -ENODEV;
> -
> if (cmd == IIO_GET_EVENT_FD_IOCTL) {
> fd = iio_event_getfd(indio_dev);
> if (fd < 0)
> @@ -278,7 +277,7 @@ long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> return -EFAULT;
> return 0;
> }
> - return -EINVAL;
> + return IIO_IOCTL_UNHANDLED;
> }
>
> static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
> @@ -286,7 +285,7 @@ static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
> {
> struct iio_event_interface *ev = filp->private_data;
>
> - return iio_device_event_ioctl(ev->indio_dev, filp, cmd, arg);
> + return iio_device_ioctl(ev->indio_dev, filp, cmd, arg);
> }
>
> static const struct file_operations iio_event_fileops = {
> @@ -308,7 +307,10 @@ void iio_device_event_attach_chrdev(struct iio_dev *indio_dev)
> cdev_init(&ev->chrdev, &iio_event_fileops);
>
> ev->indio_dev = indio_dev;
> + ev->ioctl_handler.ioctl = iio_event_ioctl;
> indio_dev->chrdev = &ev->chrdev;
> +
> + iio_device_ioctl_handler_register(indio_dev, &ev->ioctl_handler);
> }
>
> static const char * const iio_ev_type_text[] = {

2020-05-24 16:53:45

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 09/14] iio: buffer: split buffer sysfs creation to take buffer as primary arg

On Fri, 8 May 2020 16:53:43 +0300
Alexandru Ardelean <[email protected]> wrote:

> Currently the iio_buffer_{alloc,free}_sysfs_and_mask() take 'indio_dev' as
> primary argument. This change converts to take an IIO buffer as a primary
> argument.
>
> That will allow the functions to get called for multiple buffers.
>
> Signed-off-by: Alexandru Ardelean <[email protected]>

Looks good to me. We'll need this whatever the interface ends up being as
need the separate control infrastructure.

Jonathan

> ---
> drivers/iio/industrialio-buffer.c | 46 ++++++++++++++++++++-----------
> 1 file changed, 30 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index e7a847e7b103..6b1b5d5387bd 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -1312,26 +1312,14 @@ static struct attribute *iio_buffer_attrs[] = {
> &dev_attr_data_available.attr,
> };
>
> -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> +static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
> {
> + struct iio_dev *indio_dev = buffer->indio_dev;
> struct iio_dev_attr *p;
> struct attribute **attr;
> - struct iio_buffer *buffer = indio_dev->buffer;
> int ret, i, attrn, attrcount, attrcount_orig = 0;
> const struct iio_chan_spec *channels;
>
> - channels = indio_dev->channels;
> - if (channels) {
> - int ml = indio_dev->masklength;
> -
> - for (i = 0; i < indio_dev->num_channels; i++)
> - ml = max(ml, channels[i].scan_index + 1);
> - indio_dev->masklength = ml;
> - }
> -
> - if (!buffer)
> - return 0;
> -
> attrcount = 0;
> if (buffer->attrs) {
> while (buffer->attrs[attrcount] != NULL)
> @@ -1411,19 +1399,45 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> return ret;
> }
>
> -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> {
> struct iio_buffer *buffer = indio_dev->buffer;
> + const struct iio_chan_spec *channels;
> + int i;
> +
> + channels = indio_dev->channels;
> + if (channels) {
> + int ml = indio_dev->masklength;
> +
> + for (i = 0; i < indio_dev->num_channels; i++)
> + ml = max(ml, channels[i].scan_index + 1);
> + indio_dev->masklength = ml;
> + }
>
> if (!buffer)
> - return;
> + return 0;
> +
> + return __iio_buffer_alloc_sysfs_and_mask(buffer);
> +}
>
> +static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
> +{
> iio_buffer_free_scanmask(buffer);
> kfree(buffer->buffer_group.attrs);
> kfree(buffer->scan_el_group.attrs);
> iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
> }
>
> +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> +{
> + struct iio_buffer *buffer = indio_dev->buffer;
> +
> + if (!buffer)
> + return;
> +
> + __iio_buffer_free_sysfs_and_mask(buffer);
> +}
> +
> static const struct file_operations iio_buffer_fileops = {
> .read = iio_buffer_read_outer,
> .release = iio_buffer_chrdev_release,

2020-05-24 17:33:44

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 13/14] iio: unpack all iio buffer attributes correctly

On Fri, 8 May 2020 16:53:47 +0300
Alexandru Ardelean <[email protected]> wrote:

> WIP
>
> This change fixes how IIO buffer attributes get unpacked.
> There could be a saner way to unpack these without needed to change the
> drivers that attach buffer attributes incorrectly via
> iio_buffer_set_attrs()
>
> It seems that the design idea was that there is a single buffer per IIO
> device, so all drivers attached buffer attributes for FIFO to the IIO
> buffer.

Agreed - though I think what you have here is about the best we can
do and actually seems a sensible change in general.

There is a bit a mess in the abstraction, but I'm not totally sure
how to tidy that up.

These attrs are properties of the pre-demux buffer, whereas we
present them in the same directory as the post-demux buffer
(there of course can be other post-demux buffers such as in kernel
consumers). The scan_elements are a characteristic of this particular
post-demux buffer as it's length etc.

Feels like we should tidy that up, but we still potentially need
one set of these for each pre-demux buffer. Maybe we need
to explicitly call out hw fifos? It'll be a mess as sometimes
we have a single hw fifo, feeding multiple IIO devices (hopefully
just multiple buffers in the future).

Jonathan


>
> Now with the change to add a device object to the IIO buffer, and shifting
> around the device-attributes, a 'device' object unpacks to an IIO buffer
> object, which needs some special handling.'
>
> One idea to fix this, is to get rid of iio_buffer_set_attrs() somehow.
> Or, to maybe allocate some wrapper device-attributes.
>
> With this change, IIO still needs (to work with the older ABI):
> - symlink the chardev of the first IIO buffer device to the IIO device
>
> Signed-off-by: Alexandru Ardelean <[email protected]>
> ---
> drivers/iio/accel/adxl372.c | 6 ++-
> drivers/iio/accel/bmc150-accel-core.c | 6 ++-
> .../buffer/industrialio-buffer-dmaengine.c | 4 +-
> drivers/iio/industrialio-buffer.c | 51 +++++++++++--------
> include/linux/iio/buffer.h | 3 ++
> 5 files changed, 42 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
> index 60daf04ce188..528bce008671 100644
> --- a/drivers/iio/accel/adxl372.c
> +++ b/drivers/iio/accel/adxl372.c
> @@ -745,7 +745,8 @@ static ssize_t adxl372_get_fifo_enabled(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
> struct adxl372_state *st = iio_priv(indio_dev);
>
> return sprintf(buf, "%d\n", st->fifo_mode);
> @@ -755,7 +756,8 @@ static ssize_t adxl372_get_fifo_watermark(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
> struct adxl372_state *st = iio_priv(indio_dev);
>
> return sprintf(buf, "%d\n", st->watermark);
> diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
> index 121b4e89f038..c02287165980 100644
> --- a/drivers/iio/accel/bmc150-accel-core.c
> +++ b/drivers/iio/accel/bmc150-accel-core.c
> @@ -763,7 +763,8 @@ static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> int wm;
>
> @@ -778,7 +779,8 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = iio_buffer_get_attached_iio_dev(buffer);
> struct bmc150_accel_data *data = iio_priv(indio_dev);
> bool state;
>
> diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> index 6dedf12b69a4..7728fdadcc3e 100644
> --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> @@ -130,9 +130,9 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = {
> static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct iio_buffer *buffer = dev_to_iio_buffer(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);
> }
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index b14281442387..aa2f46c0949f 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -29,6 +29,19 @@ static const char * const iio_endian_prefix[] = {
> [IIO_LE] = "le",
> };
>
> +struct iio_buffer *dev_to_iio_buffer(struct device *dev)
> +{
> + return container_of(dev, struct iio_buffer, dev);
> +}
> +EXPORT_SYMBOL_GPL(dev_to_iio_buffer);
> +
> +struct iio_dev *iio_buffer_get_attached_iio_dev(struct iio_buffer *buffer)
> +{
> + return buffer ? NULL : buffer->indio_dev;
> +}
> +EXPORT_SYMBOL_GPL(iio_buffer_get_attached_iio_dev);
> +
> +
> static bool iio_buffer_is_active(struct iio_buffer *buf)
> {
> return !list_empty(&buf->buffer_list);
> @@ -324,9 +337,8 @@ static ssize_t iio_scan_el_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> int ret;
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
>
> /* Ensure ret is 0 or 1. */
> ret = !!test_bit(to_iio_dev_attr(attr)->address,
> @@ -436,10 +448,10 @@ static ssize_t iio_scan_el_store(struct device *dev,
> const char *buf,
> size_t len)
> {
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = buffer->indio_dev;
> int ret;
> bool state;
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>
> ret = strtobool(buf, &state);
> @@ -474,8 +486,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
>
> return sprintf(buf, "%d\n", buffer->scan_timestamp);
> }
> @@ -485,9 +496,9 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
> const char *buf,
> size_t len)
> {
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = buffer->indio_dev;
> int ret;
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> bool state;
>
> ret = strtobool(buf, &state);
> @@ -563,8 +574,7 @@ static ssize_t iio_buffer_read_length(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
>
> return sprintf(buf, "%d\n", buffer->length);
> }
> @@ -573,8 +583,8 @@ static ssize_t iio_buffer_write_length(struct device *dev,
> struct device_attribute *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_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = buffer->indio_dev;
> unsigned int val;
> int ret;
>
> @@ -606,8 +616,7 @@ static ssize_t iio_buffer_show_enable(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
>
> return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
> }
> @@ -1207,10 +1216,10 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
> const char *buf,
> size_t len)
> {
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = buffer->indio_dev;
> int ret;
> bool requested_state;
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> bool inlist;
>
> ret = strtobool(buf, &requested_state);
> @@ -1239,8 +1248,7 @@ static ssize_t iio_buffer_show_watermark(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
>
> return sprintf(buf, "%u\n", buffer->watermark);
> }
> @@ -1250,8 +1258,8 @@ static ssize_t iio_buffer_store_watermark(struct device *dev,
> 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_buffer *buffer = dev_to_iio_buffer(dev);
> + struct iio_dev *indio_dev = buffer->indio_dev;
> unsigned int val;
> int ret;
>
> @@ -1284,8 +1292,7 @@ static ssize_t iio_dma_show_data_available(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> {
> - struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> - struct iio_buffer *buffer = indio_dev->buffer;
> + struct iio_buffer *buffer = dev_to_iio_buffer(dev);
>
> return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
> }
> diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
> index fbba4093f06c..a688e98c694c 100644
> --- a/include/linux/iio/buffer.h
> +++ b/include/linux/iio/buffer.h
> @@ -11,6 +11,9 @@
>
> struct iio_buffer;
>
> +struct iio_buffer *dev_to_iio_buffer(struct device *dev);
> +struct iio_dev *iio_buffer_get_attached_iio_dev(struct iio_buffer *buffer);
> +
> void iio_buffer_set_attrs(struct iio_buffer *buffer,
> const struct attribute **attrs);
>

2020-05-25 07:31:05

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 09/14] iio: buffer: split buffer sysfs creation to take buffer as primary arg

On Sun, 2020-05-24 at 17:49 +0100, Jonathan Cameron wrote:
> [External]
>
> On Fri, 8 May 2020 16:53:43 +0300
> Alexandru Ardelean <[email protected]> wrote:
>
> > Currently the iio_buffer_{alloc,free}_sysfs_and_mask() take 'indio_dev' as
> > primary argument. This change converts to take an IIO buffer as a primary
> > argument.
> >
> > That will allow the functions to get called for multiple buffers.
> >
> > Signed-off-by: Alexandru Ardelean <[email protected]>
>
> Looks good to me. We'll need this whatever the interface ends up being as
> need the separate control infrastructure.

I was wanting to split this into it's own patch at some point and send it now.
I'll probably do it.

>
> Jonathan
>
> > ---
> > drivers/iio/industrialio-buffer.c | 46 ++++++++++++++++++++-----------
> > 1 file changed, 30 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-
> > buffer.c
> > index e7a847e7b103..6b1b5d5387bd 100644
> > --- a/drivers/iio/industrialio-buffer.c
> > +++ b/drivers/iio/industrialio-buffer.c
> > @@ -1312,26 +1312,14 @@ static struct attribute *iio_buffer_attrs[] = {
> > &dev_attr_data_available.attr,
> > };
> >
> > -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> > +static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
> > {
> > + struct iio_dev *indio_dev = buffer->indio_dev;
> > struct iio_dev_attr *p;
> > struct attribute **attr;
> > - struct iio_buffer *buffer = indio_dev->buffer;
> > int ret, i, attrn, attrcount, attrcount_orig = 0;
> > const struct iio_chan_spec *channels;
> >
> > - channels = indio_dev->channels;
> > - if (channels) {
> > - int ml = indio_dev->masklength;
> > -
> > - for (i = 0; i < indio_dev->num_channels; i++)
> > - ml = max(ml, channels[i].scan_index + 1);
> > - indio_dev->masklength = ml;
> > - }
> > -
> > - if (!buffer)
> > - return 0;
> > -
> > attrcount = 0;
> > if (buffer->attrs) {
> > while (buffer->attrs[attrcount] != NULL)
> > @@ -1411,19 +1399,45 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev
> > *indio_dev)
> > return ret;
> > }
> >
> > -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> > +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> > {
> > struct iio_buffer *buffer = indio_dev->buffer;
> > + const struct iio_chan_spec *channels;
> > + int i;
> > +
> > + channels = indio_dev->channels;
> > + if (channels) {
> > + int ml = indio_dev->masklength;
> > +
> > + for (i = 0; i < indio_dev->num_channels; i++)
> > + ml = max(ml, channels[i].scan_index + 1);
> > + indio_dev->masklength = ml;
> > + }
> >
> > if (!buffer)
> > - return;
> > + return 0;
> > +
> > + return __iio_buffer_alloc_sysfs_and_mask(buffer);
> > +}
> >
> > +static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
> > +{
> > iio_buffer_free_scanmask(buffer);
> > kfree(buffer->buffer_group.attrs);
> > kfree(buffer->scan_el_group.attrs);
> > iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
> > }
> >
> > +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> > +{
> > + struct iio_buffer *buffer = indio_dev->buffer;
> > +
> > + if (!buffer)
> > + return;
> > +
> > + __iio_buffer_free_sysfs_and_mask(buffer);
> > +}
> > +
> > static const struct file_operations iio_buffer_fileops = {
> > .read = iio_buffer_read_outer,
> > .release = iio_buffer_chrdev_release,

2020-05-25 08:09:11

by Alexandru Ardelean

[permalink] [raw]
Subject: Re: [RFC PATCH 08/14] iio: core: use new common ioctl() mechanism

On Sun, 2020-05-24 at 17:47 +0100, Jonathan Cameron wrote:
> [External]
>
> On Fri, 8 May 2020 16:53:42 +0300
> Alexandru Ardelean <[email protected]> wrote:
>
> > This change makes use of the new centralized ioctl() mechanism. The event
> > interface registers it's ioctl() handler to IIO device.
> > Both the buffer & event interface call 'iio_device_ioctl()', which should
> > take care of all of indio_dev's ioctl() calls.
> >
> > Later, we may add per-buffer ioctl() calls, and since each buffer will get
> > it's own chardev, the buffer ioctl() handler will need a bit of tweaking
> > for the first/legacy buffer (i.e. indio_dev->buffer).
>
> Do we have an ioctls that aren't safe if we just use them on 'any'
> buffer? I don't think we do yet, though I guess we may have in the future.
>

This was done in the idea that we may want to keep the /dev/iio:deviceX for
backwards compatibility.
But, it's undetermined yet how this will look.
I am currently working on more rework stuff [as you've seen].
I'd try to do some of the rework now, before adding more stuff [like
iio_dev_opaque].
To avoid adding this work, then having to rework it.

>
> > Also, those per-buffer ioctl() calls will not be registered with this
> > mechanism.
> >
> > Signed-off-by: Alexandru Ardelean <[email protected]>
> > ---
> > drivers/iio/iio_core.h | 3 ---
> > drivers/iio/industrialio-buffer.c | 2 +-
> > drivers/iio/industrialio-event.c | 14 ++++++++------
> > 3 files changed, 9 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
> > index 34c3e19229d8..f68de4af2738 100644
> > --- a/drivers/iio/iio_core.h
> > +++ b/drivers/iio/iio_core.h
> > @@ -54,9 +54,6 @@ ssize_t iio_format_value(char *buf, unsigned int type, int
> > size, int *vals);
> > #ifdef CONFIG_IIO_BUFFER
> > struct poll_table_struct;
> >
> > -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > - unsigned int cmd, unsigned long arg);
> > -
> > void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev);
> >
> > int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
> > diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-
> > buffer.c
> > index 1400688f5e42..e7a847e7b103 100644
> > --- a/drivers/iio/industrialio-buffer.c
> > +++ b/drivers/iio/industrialio-buffer.c
> > @@ -1199,7 +1199,7 @@ static long iio_buffer_ioctl(struct file *filep,
> > unsigned int cmd,
> > if (!buffer || !buffer->access)
> > return -ENODEV;
> >
> > - return iio_device_event_ioctl(buffer->indio_dev, filep, cmd, arg);
> > + return iio_device_ioctl(buffer->indio_dev, filep, cmd, arg);
> > }
> >
> > static ssize_t iio_buffer_store_enable(struct device *dev,
> > diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-
> > event.c
> > index 0674b2117c98..1961c1d19370 100644
> > --- a/drivers/iio/industrialio-event.c
> > +++ b/drivers/iio/industrialio-event.c
> > @@ -32,6 +32,7 @@
> > * @read_lock: lock to protect kfifo read operations
> > * @chrdev: associated chardev for this event
> > * @indio_dev: IIO device to which this event interface belongs
> > to
> > + * @ioctl_handler: handler for event ioctl() calls
> > */
> > struct iio_event_interface {
> > wait_queue_head_t wait;
> > @@ -44,6 +45,7 @@ struct iio_event_interface {
> >
> > struct cdev chrdev;
> > struct iio_dev *indio_dev;
> > + struct iio_ioctl_handler ioctl_handler;
> > };
> >
> > bool iio_event_enabled(const struct iio_event_interface *ev_int)
> > @@ -261,15 +263,12 @@ static int iio_chrdev_release(struct inode *inode,
> > struct file *filp)
> > return 0;
> > }
> >
> > -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > +static long iio_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > unsigned int cmd, unsigned long arg)
> > {
> > int __user *ip = (int __user *)arg;
> > int fd;
> >
> > - if (!indio_dev->info)
> > - return -ENODEV;
> > -
> > if (cmd == IIO_GET_EVENT_FD_IOCTL) {
> > fd = iio_event_getfd(indio_dev);
> > if (fd < 0)
> > @@ -278,7 +277,7 @@ long iio_device_event_ioctl(struct iio_dev *indio_dev,
> > struct file *filp,
> > return -EFAULT;
> > return 0;
> > }
> > - return -EINVAL;
> > + return IIO_IOCTL_UNHANDLED;
> > }
> >
> > static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
> > @@ -286,7 +285,7 @@ static long iio_event_ioctl_wrapper(struct file *filp,
> > unsigned int cmd,
> > {
> > struct iio_event_interface *ev = filp->private_data;
> >
> > - return iio_device_event_ioctl(ev->indio_dev, filp, cmd, arg);
> > + return iio_device_ioctl(ev->indio_dev, filp, cmd, arg);
> > }
> >
> > static const struct file_operations iio_event_fileops = {
> > @@ -308,7 +307,10 @@ void iio_device_event_attach_chrdev(struct iio_dev
> > *indio_dev)
> > cdev_init(&ev->chrdev, &iio_event_fileops);
> >
> > ev->indio_dev = indio_dev;
> > + ev->ioctl_handler.ioctl = iio_event_ioctl;
> > indio_dev->chrdev = &ev->chrdev;
> > +
> > + iio_device_ioctl_handler_register(indio_dev, &ev->ioctl_handler);
> > }
> >
> > static const char * const iio_ev_type_text[] = {

2020-05-31 15:24:09

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 09/14] iio: buffer: split buffer sysfs creation to take buffer as primary arg

On Mon, 25 May 2020 07:28:18 +0000
"Ardelean, Alexandru" <[email protected]> wrote:

> On Sun, 2020-05-24 at 17:49 +0100, Jonathan Cameron wrote:
> > [External]
> >
> > On Fri, 8 May 2020 16:53:43 +0300
> > Alexandru Ardelean <[email protected]> wrote:
> >
> > > Currently the iio_buffer_{alloc,free}_sysfs_and_mask() take 'indio_dev' as
> > > primary argument. This change converts to take an IIO buffer as a primary
> > > argument.
> > >
> > > That will allow the functions to get called for multiple buffers.
> > >
> > > Signed-off-by: Alexandru Ardelean <[email protected]>
> >
> > Looks good to me. We'll need this whatever the interface ends up being as
> > need the separate control infrastructure.
>
> I was wanting to split this into it's own patch at some point and send it now.
> I'll probably do it.

Great.
>
> >
> > Jonathan
> >
> > > ---
> > > drivers/iio/industrialio-buffer.c | 46 ++++++++++++++++++++-----------
> > > 1 file changed, 30 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-
> > > buffer.c
> > > index e7a847e7b103..6b1b5d5387bd 100644
> > > --- a/drivers/iio/industrialio-buffer.c
> > > +++ b/drivers/iio/industrialio-buffer.c
> > > @@ -1312,26 +1312,14 @@ static struct attribute *iio_buffer_attrs[] = {
> > > &dev_attr_data_available.attr,
> > > };
> > >
> > > -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> > > +static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer)
> > > {
> > > + struct iio_dev *indio_dev = buffer->indio_dev;
> > > struct iio_dev_attr *p;
> > > struct attribute **attr;
> > > - struct iio_buffer *buffer = indio_dev->buffer;
> > > int ret, i, attrn, attrcount, attrcount_orig = 0;
> > > const struct iio_chan_spec *channels;
> > >
> > > - channels = indio_dev->channels;
> > > - if (channels) {
> > > - int ml = indio_dev->masklength;
> > > -
> > > - for (i = 0; i < indio_dev->num_channels; i++)
> > > - ml = max(ml, channels[i].scan_index + 1);
> > > - indio_dev->masklength = ml;
> > > - }
> > > -
> > > - if (!buffer)
> > > - return 0;
> > > -
> > > attrcount = 0;
> > > if (buffer->attrs) {
> > > while (buffer->attrs[attrcount] != NULL)
> > > @@ -1411,19 +1399,45 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev
> > > *indio_dev)
> > > return ret;
> > > }
> > >
> > > -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> > > +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
> > > {
> > > struct iio_buffer *buffer = indio_dev->buffer;
> > > + const struct iio_chan_spec *channels;
> > > + int i;
> > > +
> > > + channels = indio_dev->channels;
> > > + if (channels) {
> > > + int ml = indio_dev->masklength;
> > > +
> > > + for (i = 0; i < indio_dev->num_channels; i++)
> > > + ml = max(ml, channels[i].scan_index + 1);
> > > + indio_dev->masklength = ml;
> > > + }
> > >
> > > if (!buffer)
> > > - return;
> > > + return 0;
> > > +
> > > + return __iio_buffer_alloc_sysfs_and_mask(buffer);
> > > +}
> > >
> > > +static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
> > > +{
> > > iio_buffer_free_scanmask(buffer);
> > > kfree(buffer->buffer_group.attrs);
> > > kfree(buffer->scan_el_group.attrs);
> > > iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
> > > }
> > >
> > > +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
> > > +{
> > > + struct iio_buffer *buffer = indio_dev->buffer;
> > > +
> > > + if (!buffer)
> > > + return;
> > > +
> > > + __iio_buffer_free_sysfs_and_mask(buffer);
> > > +}
> > > +
> > > static const struct file_operations iio_buffer_fileops = {
> > > .read = iio_buffer_read_outer,
> > > .release = iio_buffer_chrdev_release,

2020-05-31 15:59:19

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [RFC PATCH 08/14] iio: core: use new common ioctl() mechanism

On Mon, 25 May 2020 07:27:43 +0000
"Ardelean, Alexandru" <[email protected]> wrote:

> On Sun, 2020-05-24 at 17:47 +0100, Jonathan Cameron wrote:
> > [External]
> >
> > On Fri, 8 May 2020 16:53:42 +0300
> > Alexandru Ardelean <[email protected]> wrote:
> >
> > > This change makes use of the new centralized ioctl() mechanism. The event
> > > interface registers it's ioctl() handler to IIO device.
> > > Both the buffer & event interface call 'iio_device_ioctl()', which should
> > > take care of all of indio_dev's ioctl() calls.
> > >
> > > Later, we may add per-buffer ioctl() calls, and since each buffer will get
> > > it's own chardev, the buffer ioctl() handler will need a bit of tweaking
> > > for the first/legacy buffer (i.e. indio_dev->buffer).
> >
> > Do we have an ioctls that aren't safe if we just use them on 'any'
> > buffer? I don't think we do yet, though I guess we may have in the future.
> >
>
> This was done in the idea that we may want to keep the /dev/iio:deviceX for
> backwards compatibility.
> But, it's undetermined yet how this will look.
> I am currently working on more rework stuff [as you've seen].
> I'd try to do some of the rework now, before adding more stuff [like
> iio_dev_opaque].
> To avoid adding this work, then having to rework it.

Agreed. You are being so productive at the moment you may end up blocking
yourself. Best perhaps to slow down and clear some of the backlog.

Jonathan

>
> >
> > > Also, those per-buffer ioctl() calls will not be registered with this
> > > mechanism.
> > >
> > > Signed-off-by: Alexandru Ardelean <[email protected]>
> > > ---
> > > drivers/iio/iio_core.h | 3 ---
> > > drivers/iio/industrialio-buffer.c | 2 +-
> > > drivers/iio/industrialio-event.c | 14 ++++++++------
> > > 3 files changed, 9 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
> > > index 34c3e19229d8..f68de4af2738 100644
> > > --- a/drivers/iio/iio_core.h
> > > +++ b/drivers/iio/iio_core.h
> > > @@ -54,9 +54,6 @@ ssize_t iio_format_value(char *buf, unsigned int type, int
> > > size, int *vals);
> > > #ifdef CONFIG_IIO_BUFFER
> > > struct poll_table_struct;
> > >
> > > -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > > - unsigned int cmd, unsigned long arg);
> > > -
> > > void iio_device_buffer_attach_chrdev(struct iio_dev *indio_dev);
> > >
> > > int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
> > > diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-
> > > buffer.c
> > > index 1400688f5e42..e7a847e7b103 100644
> > > --- a/drivers/iio/industrialio-buffer.c
> > > +++ b/drivers/iio/industrialio-buffer.c
> > > @@ -1199,7 +1199,7 @@ static long iio_buffer_ioctl(struct file *filep,
> > > unsigned int cmd,
> > > if (!buffer || !buffer->access)
> > > return -ENODEV;
> > >
> > > - return iio_device_event_ioctl(buffer->indio_dev, filep, cmd, arg);
> > > + return iio_device_ioctl(buffer->indio_dev, filep, cmd, arg);
> > > }
> > >
> > > static ssize_t iio_buffer_store_enable(struct device *dev,
> > > diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-
> > > event.c
> > > index 0674b2117c98..1961c1d19370 100644
> > > --- a/drivers/iio/industrialio-event.c
> > > +++ b/drivers/iio/industrialio-event.c
> > > @@ -32,6 +32,7 @@
> > > * @read_lock: lock to protect kfifo read operations
> > > * @chrdev: associated chardev for this event
> > > * @indio_dev: IIO device to which this event interface belongs
> > > to
> > > + * @ioctl_handler: handler for event ioctl() calls
> > > */
> > > struct iio_event_interface {
> > > wait_queue_head_t wait;
> > > @@ -44,6 +45,7 @@ struct iio_event_interface {
> > >
> > > struct cdev chrdev;
> > > struct iio_dev *indio_dev;
> > > + struct iio_ioctl_handler ioctl_handler;
> > > };
> > >
> > > bool iio_event_enabled(const struct iio_event_interface *ev_int)
> > > @@ -261,15 +263,12 @@ static int iio_chrdev_release(struct inode *inode,
> > > struct file *filp)
> > > return 0;
> > > }
> > >
> > > -long iio_device_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > > +static long iio_event_ioctl(struct iio_dev *indio_dev, struct file *filp,
> > > unsigned int cmd, unsigned long arg)
> > > {
> > > int __user *ip = (int __user *)arg;
> > > int fd;
> > >
> > > - if (!indio_dev->info)
> > > - return -ENODEV;
> > > -
> > > if (cmd == IIO_GET_EVENT_FD_IOCTL) {
> > > fd = iio_event_getfd(indio_dev);
> > > if (fd < 0)
> > > @@ -278,7 +277,7 @@ long iio_device_event_ioctl(struct iio_dev *indio_dev,
> > > struct file *filp,
> > > return -EFAULT;
> > > return 0;
> > > }
> > > - return -EINVAL;
> > > + return IIO_IOCTL_UNHANDLED;
> > > }
> > >
> > > static long iio_event_ioctl_wrapper(struct file *filp, unsigned int cmd,
> > > @@ -286,7 +285,7 @@ static long iio_event_ioctl_wrapper(struct file *filp,
> > > unsigned int cmd,
> > > {
> > > struct iio_event_interface *ev = filp->private_data;
> > >
> > > - return iio_device_event_ioctl(ev->indio_dev, filp, cmd, arg);
> > > + return iio_device_ioctl(ev->indio_dev, filp, cmd, arg);
> > > }
> > >
> > > static const struct file_operations iio_event_fileops = {
> > > @@ -308,7 +307,10 @@ void iio_device_event_attach_chrdev(struct iio_dev
> > > *indio_dev)
> > > cdev_init(&ev->chrdev, &iio_event_fileops);
> > >
> > > ev->indio_dev = indio_dev;
> > > + ev->ioctl_handler.ioctl = iio_event_ioctl;
> > > indio_dev->chrdev = &ev->chrdev;
> > > +
> > > + iio_device_ioctl_handler_register(indio_dev, &ev->ioctl_handler);
> > > }
> > >
> > > static const char * const iio_ev_type_text[] = {