2020-12-22 11:02:30

by Arnaud Pouliquen

[permalink] [raw]
Subject: [PATCH v2 00/16] introduce generic IOCTL interface for RPMsg channels management

This series is a restructuring of the RPMsg char driver, to create a generic
RPMsg ioctl interface for all rpmsg services.

The RPMsg char driver provides interfaces that:
- expose a char RPMsg device for communication with the remote processor,
- expose controls interface for applications to create and release endpoints.

The objective of this series is to decorrelate the two interfaces:
- Provide a char device for a RPMsg raw service in the rpmsg_char that can be
probed by a RPMsg bus on a ns announcement.
- Generalize the use of the ioctl for all RPMsg services by creating the
rpmsg_ctrl, but keep it compatibile with the legacy.

If the V1 create a new rpmsg_raw driver in addition to the rpmsg_ctrl this
version try to reuse the rpmsg_char driver by addapting QCOM GLINK and SMD
drivers.
So a goal of this version is to help to determine the best strategy to move
forward:
- reuse rpmsg_char.
- introduce a new driver and keep rpmsg_char as a legacy driver for a while.

Notice that SMD and GLINK patches have to be tested, only build has been tested.

1) RPMsg control driver: rpmsg_ctrl.c
This driver is based on the control part of the RPMsg_char driver.
On probe a /dev/rpmsg_ctrl<X> interface is created to allow to manage the
channels.
The principles are the following:
- The RPMsg service driver registers it's name and the associated service
using the rpmsg_ctrl_unregister_ctl API. The list of supported services
is defined in include/uapi/linux/rpmsg.h and exposed to the
application thanks to a new field in rpmsg_endpoint_info struct.
- On the RPMsg bus probe(e.g virtio bus) an rpmsg_ctrl device is
registered that creates the control interface.
- The application can then create or release a channel by specifying:
- the name service
- the source address.
- the destination address.
- The rpmsg_ctrl uses the same interface than the ns announcement to
create and release the associated channel but using the driver_override
field to force the service name.
The "driver_override" allows to force the name service associated to
an RPMsg driver, bypassing the rpmsg_device_id based match check.
- At least for virtio bus, an associated ns announcement is sent to the
remote side.

2) rpmsg char driver: rpmsg_char.c
- The rpmsg class has not been removed. The associated attributes
are already available in /sys/bus/rpmsg/.
- The eptdev device is now an RPMsg device probed by a RPMsg bus driver
(probed only by the ioctl in rpmsg_char driver).

Know current Limitations:
- Tested only with virtio RPMsg bus and for one vdev instance.
- The glink and smd drivers adaptations have not been tested (not able to test).
- To limit commit and not update the IOCT interface some features have been not
implemented in this first step:
- the NS announcement as not been updated, it is not possible to create an
endpoint with a destibnation address set to RPMSG_ADDR_ANY (-1),
- not possible to destroy the channel,
- only the "rpmsg-raw" service is supported.

This series can be applied in Bjorn's rpmsg-next branch on top of the
RPMsg_ns series(4c0943255805).

This series can be tested using rpmsgexport tools available here:
https://github.com/andersson/rpmsgexport.
---
new from V1[1]:
- In V1 the rpmsg_char.c was not impacted, a rpmsg_raw.c has been created
instead.
- IOCTL interface as not been updated (to go by steps).
- smd and glink drivers has been updated to support channels creation and
release.

[1] https://patchwork.kernel.org/project/linux-remoteproc/list/?series=327277

Arnaud Pouliquen (16):
rpmsg: introduce RPMsg control driver for channel creation
rpmsg: add RPMsg control API to register service
rpmsg: add override field in channel info
rpmsg: ctrl: implement the ioctl function to create device
rpmsg: ns: initialize channel info override field
rpmsg: add helper to register the rpmsg ctrl device
rpmsg: char: clean up rpmsg class
rpmsg: char: make char rpmsg a rpmsg device without the control part
rpmsg: char: register RPMsg raw service to the ioctl interface.
rpmsg: char: allow only one endpoint per device
rpmsg: char: check destination address is not null
rpmsg: virtio: use the driver_override in channel creation ops
rpmsg: virtio: probe the rpmsg_ctl device
rpmsg: glink: add create and release rpmsg channel ops
rpmsg: smd: add create and release rpmsg channel ops
rpmsg: replace rpmsg_chrdev_register_device use

drivers/rpmsg/Kconfig | 8 +
drivers/rpmsg/Makefile | 1 +
drivers/rpmsg/qcom_glink_native.c | 96 +++++++--
drivers/rpmsg/qcom_smd.c | 59 +++++-
drivers/rpmsg/rpmsg_char.c | 246 ++++++-----------------
drivers/rpmsg/rpmsg_ctrl.c | 320 ++++++++++++++++++++++++++++++
drivers/rpmsg/rpmsg_internal.h | 14 --
drivers/rpmsg/rpmsg_ns.c | 1 +
drivers/rpmsg/virtio_rpmsg_bus.c | 38 +++-
include/linux/rpmsg.h | 40 ++++
include/uapi/linux/rpmsg.h | 14 ++
11 files changed, 606 insertions(+), 231 deletions(-)
create mode 100644 drivers/rpmsg/rpmsg_ctrl.c

--
2.17.1


2020-12-22 11:03:15

by Arnaud Pouliquen

[permalink] [raw]
Subject: [PATCH v2 07/16] rpmsg: char: clean up rpmsg class

Suppress the management of the rpmsg class as attribute. It is already
handled in /sys/bus rpmsg as specified in
documentation/ABI/testing/sysfs-bus-rpmsg.
This patch prepares the migration of the control device in rpmsg_ctrl.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/rpmsg/rpmsg_char.c | 48 --------------------------------------
1 file changed, 48 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 4bbbacdbf3bb..732f5caf068a 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -27,7 +27,6 @@
#define RPMSG_DEV_MAX (MINORMASK + 1)

static dev_t rpmsg_major;
-static struct class *rpmsg_class;

static DEFINE_IDA(rpmsg_ctrl_ida);
static DEFINE_IDA(rpmsg_ept_ida);
@@ -291,41 +290,6 @@ static const struct file_operations rpmsg_eptdev_fops = {
.compat_ioctl = compat_ptr_ioctl,
};

-static ssize_t name_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", eptdev->chinfo.name);
-}
-static DEVICE_ATTR_RO(name);
-
-static ssize_t src_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", eptdev->chinfo.src);
-}
-static DEVICE_ATTR_RO(src);
-
-static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", eptdev->chinfo.dst);
-}
-static DEVICE_ATTR_RO(dst);
-
-static struct attribute *rpmsg_eptdev_attrs[] = {
- &dev_attr_name.attr,
- &dev_attr_src.attr,
- &dev_attr_dst.attr,
- NULL
-};
-ATTRIBUTE_GROUPS(rpmsg_eptdev);
-
static void rpmsg_eptdev_release_device(struct device *dev)
{
struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
@@ -358,9 +322,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
init_waitqueue_head(&eptdev->readq);

device_initialize(dev);
- dev->class = rpmsg_class;
dev->parent = &ctrldev->dev;
- dev->groups = rpmsg_eptdev_groups;
dev_set_drvdata(dev, eptdev);

cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops);
@@ -477,7 +439,6 @@ static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
dev = &ctrldev->dev;
device_initialize(dev);
dev->parent = &rpdev->dev;
- dev->class = rpmsg_class;

cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
ctrldev->cdev.owner = THIS_MODULE;
@@ -553,17 +514,9 @@ static int rpmsg_char_init(void)
return ret;
}

- rpmsg_class = class_create(THIS_MODULE, "rpmsg");
- if (IS_ERR(rpmsg_class)) {
- pr_err("failed to create rpmsg class\n");
- unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
- return PTR_ERR(rpmsg_class);
- }
-
ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
if (ret < 0) {
pr_err("rpmsgchr: failed to register rpmsg driver\n");
- class_destroy(rpmsg_class);
unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
}

@@ -574,7 +527,6 @@ postcore_initcall(rpmsg_char_init);
static void rpmsg_chrdev_exit(void)
{
unregister_rpmsg_driver(&rpmsg_chrdev_driver);
- class_destroy(rpmsg_class);
unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
}
module_exit(rpmsg_chrdev_exit);
--
2.17.1

2020-12-22 11:03:57

by Arnaud Pouliquen

[permalink] [raw]
Subject: [PATCH v2 03/16] rpmsg: add override field in channel info

The override field is already used in the rpmsg_device.
Adding this field in the channel info allows to force the channel
creation with a specified RPMsg service driver.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
include/linux/rpmsg.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 5d64704c2346..5681c585e235 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -44,11 +44,13 @@ struct rpmsg_drv_ctrl_info {
* @name: name of service
* @src: local address
* @dst: destination address
+ * @driver_override: driver name to force a match
*/
struct rpmsg_channel_info {
char name[RPMSG_NAME_SIZE];
u32 src;
u32 dst;
+ const char *driver_override;
};

/**
--
2.17.1

2020-12-22 11:04:19

by Arnaud Pouliquen

[permalink] [raw]
Subject: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

Implement the ioctl function that parses the list of
rpmsg drivers registered to create an associated device.
To be ISO user API, in a first step, the driver_override
is only allowed for the RPMsg raw service, supported by the
rpmsg_char driver.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index 065e2e304019..8381b5b2b794 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
return 0;
}

+static const char *rpmsg_ctrl_get_drv_name(u32 service)
+{
+ struct rpmsg_ctl_info *drv_info;
+
+ list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
+ if (drv_info->ctrl->service == service)
+ return drv_info->ctrl->drv_name;
+ }
+
+ return NULL;
+}
+
static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
unsigned long arg)
{
struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
-
- dev_info(&ctrldev->dev, "Control not yet implemented\n");
+ void __user *argp = (void __user *)arg;
+ struct rpmsg_channel_info chinfo;
+ struct rpmsg_endpoint_info eptinfo;
+ struct rpmsg_device *newch;
+
+ if (cmd != RPMSG_CREATE_EPT_IOCTL)
+ return -EINVAL;
+
+ if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
+ return -EFAULT;
+
+ /*
+ * In a frst step only the rpmsg_raw service is supported.
+ * The override is foorced to RPMSG_RAW_SERVICE
+ */
+ chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
+ if (!chinfo.driver_override)
+ return -ENODEV;
+
+ memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
+ chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
+ chinfo.src = eptinfo.src;
+ chinfo.dst = eptinfo.dst;
+
+ newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
+ if (!newch) {
+ dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
+ return -ENXIO;
+ }

return 0;
};
--
2.17.1

2020-12-22 11:04:35

by Arnaud Pouliquen

[permalink] [raw]
Subject: [PATCH v2 05/16] rpmsg: ns: initialize channel info override field

By default driver_override should be 0 to avoid to force
the channel creation with a specified name.The local variable
is not initialized.

Signed-off-by: Arnaud Pouliquen <[email protected]>
---
drivers/rpmsg/rpmsg_ns.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
index 762ff1ae279f..a526bff62947 100644
--- a/drivers/rpmsg/rpmsg_ns.c
+++ b/drivers/rpmsg/rpmsg_ns.c
@@ -55,6 +55,7 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
chinfo.src = RPMSG_ADDR_ANY;
chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr);
+ chinfo.driver_override = NULL;

dev_info(dev, "%sing channel %s addr 0x%x\n",
rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ?
--
2.17.1

2021-01-04 23:16:02

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] introduce generic IOCTL interface for RPMsg channels management

On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

> This series is a restructuring of the RPMsg char driver, to create a generic
> RPMsg ioctl interface for all rpmsg services.
>
> The RPMsg char driver provides interfaces that:
> - expose a char RPMsg device for communication with the remote processor,
> - expose controls interface for applications to create and release endpoints.
>
> The objective of this series is to decorrelate the two interfaces:
> - Provide a char device for a RPMsg raw service in the rpmsg_char that can be
> probed by a RPMsg bus on a ns announcement.
> - Generalize the use of the ioctl for all RPMsg services by creating the
> rpmsg_ctrl, but keep it compatibile with the legacy.
>
> If the V1 create a new rpmsg_raw driver in addition to the rpmsg_ctrl this
> version try to reuse the rpmsg_char driver by addapting QCOM GLINK and SMD
> drivers.
> So a goal of this version is to help to determine the best strategy to move
> forward:
> - reuse rpmsg_char.
> - introduce a new driver and keep rpmsg_char as a legacy driver for a while.
>
> Notice that SMD and GLINK patches have to be tested, only build has been tested.
>
> 1) RPMsg control driver: rpmsg_ctrl.c
> This driver is based on the control part of the RPMsg_char driver.
> On probe a /dev/rpmsg_ctrl<X> interface is created to allow to manage the
> channels.
> The principles are the following:
> - The RPMsg service driver registers it's name and the associated service
> using the rpmsg_ctrl_unregister_ctl API. The list of supported services
> is defined in include/uapi/linux/rpmsg.h and exposed to the
> application thanks to a new field in rpmsg_endpoint_info struct.
> - On the RPMsg bus probe(e.g virtio bus) an rpmsg_ctrl device is
> registered that creates the control interface.
> - The application can then create or release a channel by specifying:
> - the name service
> - the source address.
> - the destination address.

Why is this useful?

> - The rpmsg_ctrl uses the same interface than the ns announcement to
> create and release the associated channel but using the driver_override
> field to force the service name.
> The "driver_override" allows to force the name service associated to
> an RPMsg driver, bypassing the rpmsg_device_id based match check.

You mean, the chinfo driver_override allows the ioctl to specify which
driver should be bound to the device created for the newly registered
endpoint?

> - At least for virtio bus, an associated ns announcement is sent to the
> remote side.
>
> 2) rpmsg char driver: rpmsg_char.c
> - The rpmsg class has not been removed. The associated attributes
> are already available in /sys/bus/rpmsg/.

So today a rpmsg_device gets the same attributes both from the class and
the bus? So the only difference is that there will no longer be a
/sys/class/rpmsg ?

Regards,
Bjorn

> - The eptdev device is now an RPMsg device probed by a RPMsg bus driver
> (probed only by the ioctl in rpmsg_char driver).
>
> Know current Limitations:
> - Tested only with virtio RPMsg bus and for one vdev instance.
> - The glink and smd drivers adaptations have not been tested (not able to test).
> - To limit commit and not update the IOCT interface some features have been not
> implemented in this first step:
> - the NS announcement as not been updated, it is not possible to create an
> endpoint with a destibnation address set to RPMSG_ADDR_ANY (-1),
> - not possible to destroy the channel,
> - only the "rpmsg-raw" service is supported.
>
> This series can be applied in Bjorn's rpmsg-next branch on top of the
> RPMsg_ns series(4c0943255805).
>
> This series can be tested using rpmsgexport tools available here:
> https://github.com/andersson/rpmsgexport.
> ---
> new from V1[1]:
> - In V1 the rpmsg_char.c was not impacted, a rpmsg_raw.c has been created
> instead.
> - IOCTL interface as not been updated (to go by steps).
> - smd and glink drivers has been updated to support channels creation and
> release.
>
> [1] https://patchwork.kernel.org/project/linux-remoteproc/list/?series=327277
>
> Arnaud Pouliquen (16):
> rpmsg: introduce RPMsg control driver for channel creation
> rpmsg: add RPMsg control API to register service
> rpmsg: add override field in channel info
> rpmsg: ctrl: implement the ioctl function to create device
> rpmsg: ns: initialize channel info override field
> rpmsg: add helper to register the rpmsg ctrl device
> rpmsg: char: clean up rpmsg class
> rpmsg: char: make char rpmsg a rpmsg device without the control part
> rpmsg: char: register RPMsg raw service to the ioctl interface.
> rpmsg: char: allow only one endpoint per device
> rpmsg: char: check destination address is not null
> rpmsg: virtio: use the driver_override in channel creation ops
> rpmsg: virtio: probe the rpmsg_ctl device
> rpmsg: glink: add create and release rpmsg channel ops
> rpmsg: smd: add create and release rpmsg channel ops
> rpmsg: replace rpmsg_chrdev_register_device use
>
> drivers/rpmsg/Kconfig | 8 +
> drivers/rpmsg/Makefile | 1 +
> drivers/rpmsg/qcom_glink_native.c | 96 +++++++--
> drivers/rpmsg/qcom_smd.c | 59 +++++-
> drivers/rpmsg/rpmsg_char.c | 246 ++++++-----------------
> drivers/rpmsg/rpmsg_ctrl.c | 320 ++++++++++++++++++++++++++++++
> drivers/rpmsg/rpmsg_internal.h | 14 --
> drivers/rpmsg/rpmsg_ns.c | 1 +
> drivers/rpmsg/virtio_rpmsg_bus.c | 38 +++-
> include/linux/rpmsg.h | 40 ++++
> include/uapi/linux/rpmsg.h | 14 ++
> 11 files changed, 606 insertions(+), 231 deletions(-)
> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>
> --
> 2.17.1
>

2021-01-05 00:41:00

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2 05/16] rpmsg: ns: initialize channel info override field

On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

> By default driver_override should be 0 to avoid to force
> the channel creation with a specified name.The local variable
> is not initialized.
>

The same problem exists in qcom_glink_native, qcom_smd and rpmsg_char.

Regards,
Bjorn

> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/rpmsg/rpmsg_ns.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
> index 762ff1ae279f..a526bff62947 100644
> --- a/drivers/rpmsg/rpmsg_ns.c
> +++ b/drivers/rpmsg/rpmsg_ns.c
> @@ -55,6 +55,7 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
> strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
> chinfo.src = RPMSG_ADDR_ANY;
> chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr);
> + chinfo.driver_override = NULL;
>
> dev_info(dev, "%sing channel %s addr 0x%x\n",
> rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ?
> --
> 2.17.1
>

2021-01-05 00:51:19

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2 07/16] rpmsg: char: clean up rpmsg class

On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

This patch doesn't "clean up" the class, as described in $subject. It
just removes it.

> Suppress the management of the rpmsg class as attribute. It is already
> handled in /sys/bus rpmsg as specified in
> documentation/ABI/testing/sysfs-bus-rpmsg.

Afaict it doesn't relate to /sys/bus/rpmsg, but rather what attributes
should be associated with the rpmsg_device (and thereby present in its
sysfs directory). But if these attributes are also added by the bus,
then why do we have this code? If that's the case this seems like a nice
cleanup that we should do outside/before merging the other patches.

> This patch prepares the migration of the control device in rpmsg_ctrl.
>

It would be useful if the commit message described how it prepares for
the migration and why.

Regards,
Bjorn

> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/rpmsg/rpmsg_char.c | 48 --------------------------------------
> 1 file changed, 48 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index 4bbbacdbf3bb..732f5caf068a 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -27,7 +27,6 @@
> #define RPMSG_DEV_MAX (MINORMASK + 1)
>
> static dev_t rpmsg_major;
> -static struct class *rpmsg_class;
>
> static DEFINE_IDA(rpmsg_ctrl_ida);
> static DEFINE_IDA(rpmsg_ept_ida);
> @@ -291,41 +290,6 @@ static const struct file_operations rpmsg_eptdev_fops = {
> .compat_ioctl = compat_ptr_ioctl,
> };
>
> -static ssize_t name_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> -{
> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> -
> - return sprintf(buf, "%s\n", eptdev->chinfo.name);
> -}
> -static DEVICE_ATTR_RO(name);
> -
> -static ssize_t src_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> -{
> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> -
> - return sprintf(buf, "%d\n", eptdev->chinfo.src);
> -}
> -static DEVICE_ATTR_RO(src);
> -
> -static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> -{
> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> -
> - return sprintf(buf, "%d\n", eptdev->chinfo.dst);
> -}
> -static DEVICE_ATTR_RO(dst);
> -
> -static struct attribute *rpmsg_eptdev_attrs[] = {
> - &dev_attr_name.attr,
> - &dev_attr_src.attr,
> - &dev_attr_dst.attr,
> - NULL
> -};
> -ATTRIBUTE_GROUPS(rpmsg_eptdev);
> -
> static void rpmsg_eptdev_release_device(struct device *dev)
> {
> struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> @@ -358,9 +322,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> init_waitqueue_head(&eptdev->readq);
>
> device_initialize(dev);
> - dev->class = rpmsg_class;
> dev->parent = &ctrldev->dev;
> - dev->groups = rpmsg_eptdev_groups;
> dev_set_drvdata(dev, eptdev);
>
> cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops);
> @@ -477,7 +439,6 @@ static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> dev = &ctrldev->dev;
> device_initialize(dev);
> dev->parent = &rpdev->dev;
> - dev->class = rpmsg_class;
>
> cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
> ctrldev->cdev.owner = THIS_MODULE;
> @@ -553,17 +514,9 @@ static int rpmsg_char_init(void)
> return ret;
> }
>
> - rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> - if (IS_ERR(rpmsg_class)) {
> - pr_err("failed to create rpmsg class\n");
> - unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> - return PTR_ERR(rpmsg_class);
> - }
> -
> ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> if (ret < 0) {
> pr_err("rpmsgchr: failed to register rpmsg driver\n");
> - class_destroy(rpmsg_class);
> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> }
>
> @@ -574,7 +527,6 @@ postcore_initcall(rpmsg_char_init);
> static void rpmsg_chrdev_exit(void)
> {
> unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> - class_destroy(rpmsg_class);
> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> }
> module_exit(rpmsg_chrdev_exit);
> --
> 2.17.1
>

2021-01-05 00:55:59

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2 07/16] rpmsg: char: clean up rpmsg class

On Mon 04 Jan 18:47 CST 2021, Bjorn Andersson wrote:

> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:
>
> This patch doesn't "clean up" the class, as described in $subject. It
> just removes it.
>
> > Suppress the management of the rpmsg class as attribute. It is already
> > handled in /sys/bus rpmsg as specified in
> > documentation/ABI/testing/sysfs-bus-rpmsg.
>
> Afaict it doesn't relate to /sys/bus/rpmsg, but rather what attributes
> should be associated with the rpmsg_device (and thereby present in its
> sysfs directory). But if these attributes are also added by the bus,
> then why do we have this code? If that's the case this seems like a nice
> cleanup that we should do outside/before merging the other patches.
>
> > This patch prepares the migration of the control device in rpmsg_ctrl.
> >
>
> It would be useful if the commit message described how it prepares for
> the migration and why.
>

Now I see what this patch does, it removes the attributes from the
character device's struct device, because they are provided by the
struct rpmsg_device's bus!

I wish your commit message made this obvious.

Also, this implies that for a few patches here rpmsg_char is just
broken - which I don't like.

Regards,
Bjorn

> Regards,
> Bjorn
>
> > Signed-off-by: Arnaud Pouliquen <[email protected]>
> > ---
> > drivers/rpmsg/rpmsg_char.c | 48 --------------------------------------
> > 1 file changed, 48 deletions(-)
> >
> > diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> > index 4bbbacdbf3bb..732f5caf068a 100644
> > --- a/drivers/rpmsg/rpmsg_char.c
> > +++ b/drivers/rpmsg/rpmsg_char.c
> > @@ -27,7 +27,6 @@
> > #define RPMSG_DEV_MAX (MINORMASK + 1)
> >
> > static dev_t rpmsg_major;
> > -static struct class *rpmsg_class;
> >
> > static DEFINE_IDA(rpmsg_ctrl_ida);
> > static DEFINE_IDA(rpmsg_ept_ida);
> > @@ -291,41 +290,6 @@ static const struct file_operations rpmsg_eptdev_fops = {
> > .compat_ioctl = compat_ptr_ioctl,
> > };
> >
> > -static ssize_t name_show(struct device *dev, struct device_attribute *attr,
> > - char *buf)
> > -{
> > - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> > -
> > - return sprintf(buf, "%s\n", eptdev->chinfo.name);
> > -}
> > -static DEVICE_ATTR_RO(name);
> > -
> > -static ssize_t src_show(struct device *dev, struct device_attribute *attr,
> > - char *buf)
> > -{
> > - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> > -
> > - return sprintf(buf, "%d\n", eptdev->chinfo.src);
> > -}
> > -static DEVICE_ATTR_RO(src);
> > -
> > -static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
> > - char *buf)
> > -{
> > - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> > -
> > - return sprintf(buf, "%d\n", eptdev->chinfo.dst);
> > -}
> > -static DEVICE_ATTR_RO(dst);
> > -
> > -static struct attribute *rpmsg_eptdev_attrs[] = {
> > - &dev_attr_name.attr,
> > - &dev_attr_src.attr,
> > - &dev_attr_dst.attr,
> > - NULL
> > -};
> > -ATTRIBUTE_GROUPS(rpmsg_eptdev);
> > -
> > static void rpmsg_eptdev_release_device(struct device *dev)
> > {
> > struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> > @@ -358,9 +322,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> > init_waitqueue_head(&eptdev->readq);
> >
> > device_initialize(dev);
> > - dev->class = rpmsg_class;
> > dev->parent = &ctrldev->dev;
> > - dev->groups = rpmsg_eptdev_groups;
> > dev_set_drvdata(dev, eptdev);
> >
> > cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops);
> > @@ -477,7 +439,6 @@ static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> > dev = &ctrldev->dev;
> > device_initialize(dev);
> > dev->parent = &rpdev->dev;
> > - dev->class = rpmsg_class;
> >
> > cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
> > ctrldev->cdev.owner = THIS_MODULE;
> > @@ -553,17 +514,9 @@ static int rpmsg_char_init(void)
> > return ret;
> > }
> >
> > - rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> > - if (IS_ERR(rpmsg_class)) {
> > - pr_err("failed to create rpmsg class\n");
> > - unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> > - return PTR_ERR(rpmsg_class);
> > - }
> > -
> > ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> > if (ret < 0) {
> > pr_err("rpmsgchr: failed to register rpmsg driver\n");
> > - class_destroy(rpmsg_class);
> > unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> > }
> >
> > @@ -574,7 +527,6 @@ postcore_initcall(rpmsg_char_init);
> > static void rpmsg_chrdev_exit(void)
> > {
> > unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> > - class_destroy(rpmsg_class);
> > unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> > }
> > module_exit(rpmsg_chrdev_exit);
> > --
> > 2.17.1
> >

2021-01-05 01:37:14

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

> Implement the ioctl function that parses the list of
> rpmsg drivers registered to create an associated device.
> To be ISO user API, in a first step, the driver_override
> is only allowed for the RPMsg raw service, supported by the
> rpmsg_char driver.
>
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 41 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
> index 065e2e304019..8381b5b2b794 100644
> --- a/drivers/rpmsg/rpmsg_ctrl.c
> +++ b/drivers/rpmsg/rpmsg_ctrl.c
> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
> return 0;
> }
>
> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
> +{
> + struct rpmsg_ctl_info *drv_info;
> +
> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
> + if (drv_info->ctrl->service == service)
> + return drv_info->ctrl->drv_name;
> + }
> +
> + return NULL;
> +}
> +
> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
> unsigned long arg)
> {
> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
> -
> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
> + void __user *argp = (void __user *)arg;
> + struct rpmsg_channel_info chinfo;
> + struct rpmsg_endpoint_info eptinfo;
> + struct rpmsg_device *newch;
> +
> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> + return -EINVAL;
> +
> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> + return -EFAULT;
> +
> + /*
> + * In a frst step only the rpmsg_raw service is supported.
> + * The override is foorced to RPMSG_RAW_SERVICE
> + */
> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
> + if (!chinfo.driver_override)
> + return -ENODEV;
> +
> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
> + chinfo.src = eptinfo.src;
> + chinfo.dst = eptinfo.dst;
> +
> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);

Afaict this would create and announce and endpoint (or possibly find a
endpoint announced by the other side of the link).

In the case of the Qualcomm transports, and as been discussed to
introduce for virtio in the past, the channel actually have a state. So
opening/announcing it here means that we have no way to close and reopen
this channel later?


It would also mean that we announce to the firmware that there's an
application in Linux now ready to receive data on this channel - but
that won't be the case until someone actually open the created cdev (or
tty in your case) - which quite likely will result in data loss.

I think instead of piggybacking on the rpmsg_device we should just carry
these "raw exports to userspace" in some other construct - perhaps a
auxiliary_bus, or if we still only care for char and tty, not split them
up at all using the device model.

Regards,
Bjorn

> + if (!newch) {
> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
> + return -ENXIO;
> + }
>
> return 0;
> };
> --
> 2.17.1
>

2021-01-05 17:02:57

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] introduce generic IOCTL interface for RPMsg channels management

Hello Bjorn,

On 1/5/21 12:03 AM, Bjorn Andersson wrote:
> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:
>
>> This series is a restructuring of the RPMsg char driver, to create a generic
>> RPMsg ioctl interface for all rpmsg services.
>>
>> The RPMsg char driver provides interfaces that:
>> - expose a char RPMsg device for communication with the remote processor,
>> - expose controls interface for applications to create and release endpoints.
>>
>> The objective of this series is to decorrelate the two interfaces:
>> - Provide a char device for a RPMsg raw service in the rpmsg_char that can be
>> probed by a RPMsg bus on a ns announcement.
>> - Generalize the use of the ioctl for all RPMsg services by creating the
>> rpmsg_ctrl, but keep it compatibile with the legacy.
>>
>> If the V1 create a new rpmsg_raw driver in addition to the rpmsg_ctrl this
>> version try to reuse the rpmsg_char driver by addapting QCOM GLINK and SMD
>> drivers.
>> So a goal of this version is to help to determine the best strategy to move
>> forward:
>> - reuse rpmsg_char.
>> - introduce a new driver and keep rpmsg_char as a legacy driver for a while.
>>
>> Notice that SMD and GLINK patches have to be tested, only build has been tested.
>>
>> 1) RPMsg control driver: rpmsg_ctrl.c
>> This driver is based on the control part of the RPMsg_char driver.
>> On probe a /dev/rpmsg_ctrl<X> interface is created to allow to manage the
>> channels.
>> The principles are the following:
>> - The RPMsg service driver registers it's name and the associated service
>> using the rpmsg_ctrl_unregister_ctl API. The list of supported services
>> is defined in include/uapi/linux/rpmsg.h and exposed to the
>> application thanks to a new field in rpmsg_endpoint_info struct.
>> - On the RPMsg bus probe(e.g virtio bus) an rpmsg_ctrl device is
>> registered that creates the control interface.
>> - The application can then create or release a channel by specifying:
>> - the name service
>> - the source address.
>> - the destination address.
>
> Why is this useful?
I'm not sure to understand what is behind your question.
I guess the question is why is it useful to create a channel?
Mainly to use same way to probe a RPMsg service than the NS announcement.

>
>> - The rpmsg_ctrl uses the same interface than the ns announcement to
>> create and release the associated channel but using the driver_override
>> field to force the service name.
>> The "driver_override" allows to force the name service associated to
>> an RPMsg driver, bypassing the rpmsg_device_id based match check.
>
> You mean, the chinfo driver_override allows the ioctl to specify which
> driver should be bound to the device created for the newly registered
> endpoint?

Yes exactly, this is the main point of the proposal. Having the same RPMsg
driver that can be probed either by the remote side using the NS announcement
mechanism or by the rpmsg ctrl interface.
The driver "just" has to register to the RPMsg ctrl which service it supports.

>
>> - At least for virtio bus, an associated ns announcement is sent to the
>> remote side.
>>
>> 2) rpmsg char driver: rpmsg_char.c
>> - The rpmsg class has not been removed. The associated attributes
>> are already available in /sys/bus/rpmsg/.
>
> So today a rpmsg_device gets the same attributes both from the class and
> the bus? So the only difference is that there will no longer be a
> /sys/class/rpmsg ?

Yes, if the rpmsg_char is probed by the bus,
My proposal is to suppress attributes in /sys/class/rpmsg as they are already
defined in /sys/bus/rpmsg/devices/
But class attribute can be kept if needed...

Thanks,
Arnaud

>
> Regards,
> Bjorn
>
>> - The eptdev device is now an RPMsg device probed by a RPMsg bus driver
>> (probed only by the ioctl in rpmsg_char driver).
>>
>> Know current Limitations:
>> - Tested only with virtio RPMsg bus and for one vdev instance.
>> - The glink and smd drivers adaptations have not been tested (not able to test).
>> - To limit commit and not update the IOCT interface some features have been not
>> implemented in this first step:
>> - the NS announcement as not been updated, it is not possible to create an
>> endpoint with a destibnation address set to RPMSG_ADDR_ANY (-1),
>> - not possible to destroy the channel,
>> - only the "rpmsg-raw" service is supported.
>>
>> This series can be applied in Bjorn's rpmsg-next branch on top of the
>> RPMsg_ns series(4c0943255805).
>>
>> This series can be tested using rpmsgexport tools available here:
>> https://github.com/andersson/rpmsgexport.
>> ---
>> new from V1[1]:
>> - In V1 the rpmsg_char.c was not impacted, a rpmsg_raw.c has been created
>> instead.
>> - IOCTL interface as not been updated (to go by steps).
>> - smd and glink drivers has been updated to support channels creation and
>> release.
>>
>> [1] https://patchwork.kernel.org/project/linux-remoteproc/list/?series=327277
>>
>> Arnaud Pouliquen (16):
>> rpmsg: introduce RPMsg control driver for channel creation
>> rpmsg: add RPMsg control API to register service
>> rpmsg: add override field in channel info
>> rpmsg: ctrl: implement the ioctl function to create device
>> rpmsg: ns: initialize channel info override field
>> rpmsg: add helper to register the rpmsg ctrl device
>> rpmsg: char: clean up rpmsg class
>> rpmsg: char: make char rpmsg a rpmsg device without the control part
>> rpmsg: char: register RPMsg raw service to the ioctl interface.
>> rpmsg: char: allow only one endpoint per device
>> rpmsg: char: check destination address is not null
>> rpmsg: virtio: use the driver_override in channel creation ops
>> rpmsg: virtio: probe the rpmsg_ctl device
>> rpmsg: glink: add create and release rpmsg channel ops
>> rpmsg: smd: add create and release rpmsg channel ops
>> rpmsg: replace rpmsg_chrdev_register_device use
>>
>> drivers/rpmsg/Kconfig | 8 +
>> drivers/rpmsg/Makefile | 1 +
>> drivers/rpmsg/qcom_glink_native.c | 96 +++++++--
>> drivers/rpmsg/qcom_smd.c | 59 +++++-
>> drivers/rpmsg/rpmsg_char.c | 246 ++++++-----------------
>> drivers/rpmsg/rpmsg_ctrl.c | 320 ++++++++++++++++++++++++++++++
>> drivers/rpmsg/rpmsg_internal.h | 14 --
>> drivers/rpmsg/rpmsg_ns.c | 1 +
>> drivers/rpmsg/virtio_rpmsg_bus.c | 38 +++-
>> include/linux/rpmsg.h | 40 ++++
>> include/uapi/linux/rpmsg.h | 14 ++
>> 11 files changed, 606 insertions(+), 231 deletions(-)
>> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>>
>> --
>> 2.17.1
>>

2021-01-05 17:05:39

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 05/16] rpmsg: ns: initialize channel info override field



On 1/5/21 1:38 AM, Bjorn Andersson wrote:
> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:
>
>> By default driver_override should be 0 to avoid to force
>> the channel creation with a specified name.The local variable
>> is not initialized.
>>
>
> The same problem exists in qcom_glink_native, qcom_smd and rpmsg_char.

Right! And perhaps initializing the structure on declaration would be a better
method.

Thanks,
Arnaud

>
> Regards,
> Bjorn
>
>> Signed-off-by: Arnaud Pouliquen <[email protected]>
>> ---
>> drivers/rpmsg/rpmsg_ns.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/rpmsg/rpmsg_ns.c b/drivers/rpmsg/rpmsg_ns.c
>> index 762ff1ae279f..a526bff62947 100644
>> --- a/drivers/rpmsg/rpmsg_ns.c
>> +++ b/drivers/rpmsg/rpmsg_ns.c
>> @@ -55,6 +55,7 @@ static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
>> strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
>> chinfo.src = RPMSG_ADDR_ANY;
>> chinfo.dst = rpmsg32_to_cpu(rpdev, msg->addr);
>> + chinfo.driver_override = NULL;
>>
>> dev_info(dev, "%sing channel %s addr 0x%x\n",
>> rpmsg32_to_cpu(rpdev, msg->flags) & RPMSG_NS_DESTROY ?
>> --
>> 2.17.1
>>

2021-01-05 17:06:52

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 07/16] rpmsg: char: clean up rpmsg class



On 1/5/21 1:54 AM, Bjorn Andersson wrote:
> On Mon 04 Jan 18:47 CST 2021, Bjorn Andersson wrote:
>
>> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:
>>
>> This patch doesn't "clean up" the class, as described in $subject. It
>> just removes it.
>>
>>> Suppress the management of the rpmsg class as attribute. It is already
>>> handled in /sys/bus rpmsg as specified in
>>> documentation/ABI/testing/sysfs-bus-rpmsg.
>>
>> Afaict it doesn't relate to /sys/bus/rpmsg, but rather what attributes
>> should be associated with the rpmsg_device (and thereby present in its
>> sysfs directory). But if these attributes are also added by the bus,
>> then why do we have this code? If that's the case this seems like a nice
>> cleanup that we should do outside/before merging the other patches.
>>
>>> This patch prepares the migration of the control device in rpmsg_ctrl.
>>>
>>
>> It would be useful if the commit message described how it prepares for
>> the migration and why.
>>
>
> Now I see what this patch does, it removes the attributes from the
> character device's struct device, because they are provided by the
> struct rpmsg_device's bus!
>
> I wish your commit message made this obvious.
>
> Also, this implies that for a few patches here rpmsg_char is just
> broken - which I don't like.

I will move this patch at the end of the series and clarify commit message

Thanks
Arnaud

>
> Regards,
> Bjorn
>
>> Regards,
>> Bjorn
>>
>>> Signed-off-by: Arnaud Pouliquen <[email protected]>
>>> ---
>>> drivers/rpmsg/rpmsg_char.c | 48 --------------------------------------
>>> 1 file changed, 48 deletions(-)
>>>
>>> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
>>> index 4bbbacdbf3bb..732f5caf068a 100644
>>> --- a/drivers/rpmsg/rpmsg_char.c
>>> +++ b/drivers/rpmsg/rpmsg_char.c
>>> @@ -27,7 +27,6 @@
>>> #define RPMSG_DEV_MAX (MINORMASK + 1)
>>>
>>> static dev_t rpmsg_major;
>>> -static struct class *rpmsg_class;
>>>
>>> static DEFINE_IDA(rpmsg_ctrl_ida);
>>> static DEFINE_IDA(rpmsg_ept_ida);
>>> @@ -291,41 +290,6 @@ static const struct file_operations rpmsg_eptdev_fops = {
>>> .compat_ioctl = compat_ptr_ioctl,
>>> };
>>>
>>> -static ssize_t name_show(struct device *dev, struct device_attribute *attr,
>>> - char *buf)
>>> -{
>>> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
>>> -
>>> - return sprintf(buf, "%s\n", eptdev->chinfo.name);
>>> -}
>>> -static DEVICE_ATTR_RO(name);
>>> -
>>> -static ssize_t src_show(struct device *dev, struct device_attribute *attr,
>>> - char *buf)
>>> -{
>>> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
>>> -
>>> - return sprintf(buf, "%d\n", eptdev->chinfo.src);
>>> -}
>>> -static DEVICE_ATTR_RO(src);
>>> -
>>> -static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
>>> - char *buf)
>>> -{
>>> - struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
>>> -
>>> - return sprintf(buf, "%d\n", eptdev->chinfo.dst);
>>> -}
>>> -static DEVICE_ATTR_RO(dst);
>>> -
>>> -static struct attribute *rpmsg_eptdev_attrs[] = {
>>> - &dev_attr_name.attr,
>>> - &dev_attr_src.attr,
>>> - &dev_attr_dst.attr,
>>> - NULL
>>> -};
>>> -ATTRIBUTE_GROUPS(rpmsg_eptdev);
>>> -
>>> static void rpmsg_eptdev_release_device(struct device *dev)
>>> {
>>> struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
>>> @@ -358,9 +322,7 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
>>> init_waitqueue_head(&eptdev->readq);
>>>
>>> device_initialize(dev);
>>> - dev->class = rpmsg_class;
>>> dev->parent = &ctrldev->dev;
>>> - dev->groups = rpmsg_eptdev_groups;
>>> dev_set_drvdata(dev, eptdev);
>>>
>>> cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops);
>>> @@ -477,7 +439,6 @@ static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
>>> dev = &ctrldev->dev;
>>> device_initialize(dev);
>>> dev->parent = &rpdev->dev;
>>> - dev->class = rpmsg_class;
>>>
>>> cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
>>> ctrldev->cdev.owner = THIS_MODULE;
>>> @@ -553,17 +514,9 @@ static int rpmsg_char_init(void)
>>> return ret;
>>> }
>>>
>>> - rpmsg_class = class_create(THIS_MODULE, "rpmsg");
>>> - if (IS_ERR(rpmsg_class)) {
>>> - pr_err("failed to create rpmsg class\n");
>>> - unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>> - return PTR_ERR(rpmsg_class);
>>> - }
>>> -
>>> ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
>>> if (ret < 0) {
>>> pr_err("rpmsgchr: failed to register rpmsg driver\n");
>>> - class_destroy(rpmsg_class);
>>> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>> }
>>>
>>> @@ -574,7 +527,6 @@ postcore_initcall(rpmsg_char_init);
>>> static void rpmsg_chrdev_exit(void)
>>> {
>>> unregister_rpmsg_driver(&rpmsg_chrdev_driver);
>>> - class_destroy(rpmsg_class);
>>> unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
>>> }
>>> module_exit(rpmsg_chrdev_exit);
>>> --
>>> 2.17.1
>>>

2021-01-05 18:11:30

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device



On 1/5/21 2:33 AM, Bjorn Andersson wrote:
> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:
>
>> Implement the ioctl function that parses the list of
>> rpmsg drivers registered to create an associated device.
>> To be ISO user API, in a first step, the driver_override
>> is only allowed for the RPMsg raw service, supported by the
>> rpmsg_char driver.
>>
>> Signed-off-by: Arnaud Pouliquen <[email protected]>
>> ---
>> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
>> index 065e2e304019..8381b5b2b794 100644
>> --- a/drivers/rpmsg/rpmsg_ctrl.c
>> +++ b/drivers/rpmsg/rpmsg_ctrl.c
>> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
>> return 0;
>> }
>>
>> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
>> +{
>> + struct rpmsg_ctl_info *drv_info;
>> +
>> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
>> + if (drv_info->ctrl->service == service)
>> + return drv_info->ctrl->drv_name;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
>> unsigned long arg)
>> {
>> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
>> -
>> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
>> + void __user *argp = (void __user *)arg;
>> + struct rpmsg_channel_info chinfo;
>> + struct rpmsg_endpoint_info eptinfo;
>> + struct rpmsg_device *newch;
>> +
>> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
>> + return -EINVAL;
>> +
>> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
>> + return -EFAULT;
>> +
>> + /*
>> + * In a frst step only the rpmsg_raw service is supported.
>> + * The override is foorced to RPMSG_RAW_SERVICE
>> + */
>> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
>> + if (!chinfo.driver_override)
>> + return -ENODEV;
>> +
>> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
>> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
>> + chinfo.src = eptinfo.src;
>> + chinfo.dst = eptinfo.dst;
>> +
>> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
>
> Afaict this would create and announce and endpoint (or possibly find a
> endpoint announced by the other side of the link).

It depends on how rpdev is initialized[1].
- For the rpmsg_char no default endpoint is created. The endpoint is created on
/dev/rpmsgX open. So the channel is created but not announced.
=> both sides have to know the the destination address for virtio implementation.

- For the rpmsg TTY the endpoint should be created by default by the RPMsg core
and associated to the rpdev. An announcement is sent to the remote side.

[1]https://elixir.bootlin.com/linux/latest/source/drivers/rpmsg/rpmsg_core.c#L445

>
> In the case of the Qualcomm transports, and as been discussed to
> introduce for virtio in the past, the channel actually have a state. So
> opening/announcing it here means that we have no way to close and reopen
> this channel later?

In this first series I just focused to de-correlate the control part from the
rpmsg char. A main difference is that a channel is associated to a cdev.

But the ioctrl can be extended to close the cdev and the associated channel
(implemented in my V1).
else the rpmsg device is automatically remove by the rpmsg bus.
>
>
> It would also mean that we announce to the firmware that there's an
> application in Linux now ready to receive data on this channel - but
> that won't be the case until someone actually open the created cdev (or
> tty in your case) - which quite likely will result in data loss.

With the virtio implementation it is potentially already the case. When Linux
receive an NS announcement, there is no mechanism to inform the remote firmware
that Linux is ready to receive data. Some OpenAMP lib user already point out
this issue.
In glink driver seems that there is no such issue as
qcom_glink_send_open/close_req allow to provide information on endpoint state.

I would propose to address this in a next step.

>
> I think instead of piggybacking on the rpmsg_device we should just carry
> these "raw exports to userspace" in some other construct - perhaps a
> auxiliary_bus,

I'm not familiar with auxilary-bus but seems very similar to the rpmsg_bus...
I wonder if this could lead to code duplication in RPMsg service drivers to
support the control but also the NS announcement.

or if we still only care for char and tty, not split them
> up at all using the device model.

The initial requirement was to extend the control interface implemented in
rpmsg_char to other services before introducing new one.

So probably as a first step we have to clarify the requirements to determine the
solution to implement.

Here is my point of view on the induced requirements:
- Allow to create a service from Linux user application:
- with a specific name
- with or without name service announcement.
- Allow to probe the same service by receiving either a NS announcement from the
remote firmware or a Linux user application request.
- Use these services independently of the RPMsg transport implementation (e.g be
able to use RPMSg char with the RPMsg virtio bus).

This requirements explain my approach: associate a service to a RPMsg device in
order to be able to probe using the same driver either by the remote firmware NS
announcement or by a Linux user application.

Is the requirements I detailed match with what you had in mind?

Please, could you detail your views on the use of the auxilary bus in this context?

We can also think about an alternative to keep rpmsg_char unchanged for legacy
support.
- only create a RPMsg ctrl for new RPMsg services
- enable it for virtio_rpmsg_bus (In this case the rpmsg char cannot be probed
by remote firmware, but allows communication between fixed addresses)

Thanks,
Arnaud

>
> Regards,
> Bjorn
>
>> + if (!newch) {
>> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
>> + return -ENXIO;
>> + }
>>
>> return 0;
>> };
>> --
>> 2.17.1
>>

2021-01-13 20:33:43

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] introduce generic IOCTL interface for RPMsg channels management

Hi Arnaud,

[...]

>
> Arnaud Pouliquen (16):
> rpmsg: introduce RPMsg control driver for channel creation
> rpmsg: add RPMsg control API to register service
> rpmsg: add override field in channel info
> rpmsg: ctrl: implement the ioctl function to create device
> rpmsg: ns: initialize channel info override field
> rpmsg: add helper to register the rpmsg ctrl device
> rpmsg: char: clean up rpmsg class
> rpmsg: char: make char rpmsg a rpmsg device without the control part
> rpmsg: char: register RPMsg raw service to the ioctl interface.
> rpmsg: char: allow only one endpoint per device
> rpmsg: char: check destination address is not null
> rpmsg: virtio: use the driver_override in channel creation ops
> rpmsg: virtio: probe the rpmsg_ctl device
> rpmsg: glink: add create and release rpmsg channel ops
> rpmsg: smd: add create and release rpmsg channel ops
> rpmsg: replace rpmsg_chrdev_register_device use
>
> drivers/rpmsg/Kconfig | 8 +
> drivers/rpmsg/Makefile | 1 +
> drivers/rpmsg/qcom_glink_native.c | 96 +++++++--
> drivers/rpmsg/qcom_smd.c | 59 +++++-
> drivers/rpmsg/rpmsg_char.c | 246 ++++++-----------------
> drivers/rpmsg/rpmsg_ctrl.c | 320 ++++++++++++++++++++++++++++++
> drivers/rpmsg/rpmsg_internal.h | 14 --
> drivers/rpmsg/rpmsg_ns.c | 1 +
> drivers/rpmsg/virtio_rpmsg_bus.c | 38 +++-
> include/linux/rpmsg.h | 40 ++++
> include/uapi/linux/rpmsg.h | 14 ++
> 11 files changed, 606 insertions(+), 231 deletions(-)
> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c

I am finally coming around to review this set. I see that you already had an
extensive conversation with Bjorn - did you want me to have a look as well or
should I wait for the next revision?

Thanks,
Mathieu

>
> --
> 2.17.1
>

2021-01-14 09:09:41

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] introduce generic IOCTL interface for RPMsg channels management

Hi Mathieu,

On 1/13/21 9:31 PM, Mathieu Poirier wrote:
> Hi Arnaud,
>
> [...]
>
>>
>> Arnaud Pouliquen (16):
>> rpmsg: introduce RPMsg control driver for channel creation
>> rpmsg: add RPMsg control API to register service
>> rpmsg: add override field in channel info
>> rpmsg: ctrl: implement the ioctl function to create device
>> rpmsg: ns: initialize channel info override field
>> rpmsg: add helper to register the rpmsg ctrl device
>> rpmsg: char: clean up rpmsg class
>> rpmsg: char: make char rpmsg a rpmsg device without the control part
>> rpmsg: char: register RPMsg raw service to the ioctl interface.
>> rpmsg: char: allow only one endpoint per device
>> rpmsg: char: check destination address is not null
>> rpmsg: virtio: use the driver_override in channel creation ops
>> rpmsg: virtio: probe the rpmsg_ctl device
>> rpmsg: glink: add create and release rpmsg channel ops
>> rpmsg: smd: add create and release rpmsg channel ops
>> rpmsg: replace rpmsg_chrdev_register_device use
>>
>> drivers/rpmsg/Kconfig | 8 +
>> drivers/rpmsg/Makefile | 1 +
>> drivers/rpmsg/qcom_glink_native.c | 96 +++++++--
>> drivers/rpmsg/qcom_smd.c | 59 +++++-
>> drivers/rpmsg/rpmsg_char.c | 246 ++++++-----------------
>> drivers/rpmsg/rpmsg_ctrl.c | 320 ++++++++++++++++++++++++++++++
>> drivers/rpmsg/rpmsg_internal.h | 14 --
>> drivers/rpmsg/rpmsg_ns.c | 1 +
>> drivers/rpmsg/virtio_rpmsg_bus.c | 38 +++-
>> include/linux/rpmsg.h | 40 ++++
>> include/uapi/linux/rpmsg.h | 14 ++
>> 11 files changed, 606 insertions(+), 231 deletions(-)
>> create mode 100644 drivers/rpmsg/rpmsg_ctrl.c
>
> I am finally coming around to review this set. I see that you already had an
> extensive conversation with Bjorn - did you want me to have a look as well or
> should I wait for the next revision?

Based on Bjorn first feedback, my understanding is that the management based on
create/destroy channel does not match with the QCOM RPMsg backend
implementation. I think this is the blocking point of my V2 implementation.

Before sending a new revision i would hope that we have a roundtable discussion
to clarify the direction to move forward, to avoid sending useless revisions.

As discussed in [1], there are different alternatives, that probably depend on
the features we expect to support.
I tried to sum-up the requirement I have in mind in [1].

The 2 main directions I can see are:
- rework the rpmsg_char to match with all rpmsg backend (V2 implementation)
to be honest i don't know how to move forward in this direction as QCOM and
virtio backends are rather different.
- not modify the rpmsg_char but create the rpmsg_ctrl (and perhaps also a
rpmsg_raw for a /dev/rpmsg data interface) that would use the create/destroy
channel such as the rpmsg ns (V1 implementation).
one advantage of this solution is that this does not impact QCOM drivers.
one drawback is that we duplicate the code.

[1]
https://patchwork.kernel.org/project/linux-remoteproc/patch/[email protected]/

[2] https://patchwork.kernel.org/project/linux-remoteproc/list/?series=327277

Thanks,
Arnaud

>
> Thanks,
> Mathieu
>
>>
>> --
>> 2.17.1
>>

2021-01-22 01:03:10

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

On Tue, Dec 22, 2020 at 11:57:14AM +0100, Arnaud Pouliquen wrote:
> Implement the ioctl function that parses the list of
> rpmsg drivers registered to create an associated device.
> To be ISO user API, in a first step, the driver_override
> is only allowed for the RPMsg raw service, supported by the
> rpmsg_char driver.
>
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 41 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
> index 065e2e304019..8381b5b2b794 100644
> --- a/drivers/rpmsg/rpmsg_ctrl.c
> +++ b/drivers/rpmsg/rpmsg_ctrl.c
> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
> return 0;
> }
>
> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
> +{
> + struct rpmsg_ctl_info *drv_info;
> +
> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
> + if (drv_info->ctrl->service == service)
> + return drv_info->ctrl->drv_name;
> + }
> +

I'm unsure about the above... To me this looks like what the .match() function
of a bus would do. And when I read Bjorn's comment he brought up the
auxiliary_bus. I don't know about the auxiliary_bus but it is worth looking
into. Registering with a bus would streamline a lot of the code in this
patchset.

I'm out of time for today - I will continue tomorrow.

Thanks,
Mathieu

> + return NULL;
> +}
> +
> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
> unsigned long arg)
> {
> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
> -
> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
> + void __user *argp = (void __user *)arg;
> + struct rpmsg_channel_info chinfo;
> + struct rpmsg_endpoint_info eptinfo;
> + struct rpmsg_device *newch;
> +
> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> + return -EINVAL;
> +
> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> + return -EFAULT;
> +
> + /*
> + * In a frst step only the rpmsg_raw service is supported.
> + * The override is foorced to RPMSG_RAW_SERVICE
> + */
> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
> + if (!chinfo.driver_override)
> + return -ENODEV;
> +
> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
> + chinfo.src = eptinfo.src;
> + chinfo.dst = eptinfo.dst;
> +
> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
> + if (!newch) {
> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
> + return -ENXIO;
> + }
>
> return 0;
> };
> --
> 2.17.1
>

2021-01-22 13:10:39

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

Hi Mathieu,

On 1/22/21 12:52 AM, Mathieu Poirier wrote:
> On Tue, Dec 22, 2020 at 11:57:14AM +0100, Arnaud Pouliquen wrote:
>> Implement the ioctl function that parses the list of
>> rpmsg drivers registered to create an associated device.
>> To be ISO user API, in a first step, the driver_override
>> is only allowed for the RPMsg raw service, supported by the
>> rpmsg_char driver.
>>
>> Signed-off-by: Arnaud Pouliquen <[email protected]>
>> ---
>> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
>> index 065e2e304019..8381b5b2b794 100644
>> --- a/drivers/rpmsg/rpmsg_ctrl.c
>> +++ b/drivers/rpmsg/rpmsg_ctrl.c
>> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
>> return 0;
>> }
>>
>> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
>> +{
>> + struct rpmsg_ctl_info *drv_info;
>> +
>> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
>> + if (drv_info->ctrl->service == service)
>> + return drv_info->ctrl->drv_name;
>> + }
>> +
>
> I'm unsure about the above... To me this looks like what the .match() function
> of a bus would do. And when I read Bjorn's comment he brought up the
> auxiliary_bus. I don't know about the auxiliary_bus but it is worth looking
> into. Registering with a bus would streamline a lot of the code in this
> patchset.

As answered Bjorn, we already have the RPMsg bus to manage the rpmsg devices.
Look like duplication from my POV, except if the IOCTL does not manage channel
but only endpoint.

In my design I considered that the rpmsg_ctrl creates a channel associated to a
rpmsg_device such as the RPMsg ns_announcement.

Based on this assumption, if we implement the auxiliary_bus (or other) for the
rpmsg_ctrl a RPMsg driver will have to manage the probe by rpmsg_bus and by the
auxillary bus. The probe from the auxiliary bus would lead to the creation of an
RPMsg device on the rpmsg_bus, so a duplication with cross dependencies and
would probably make tricky the remove part.

That said, I think the design depends on the functionality that should be
implemented in the rpmsg_ctrl. Here is an alternative approach based on the
auxiliary bus, which I'm starting to think about:

The current approach of the rpmsg_char driver is to use the IOCTRL interface to
instantiate a cdev with an endpoint (the RPMsg device is associated with the
ioctl dev). This would correspond to the use of an auxiliary bus to manage local
endpoint creations.

We could therefore consider an RPMsg name service based on an RPmsg device. This
RPMsg device would register a kind of "RPMsg service endpoint" driver on the
auxiliary rpmsg_ioctl bus.
The rpmsg_ctrl will be used to instantiate the endpoints for this RPMsg device.
on user application request the rpmsg_ctrl will call the appropriate auxiliary
device to create an endpoint.

If we consider that one objective of this series is to allow application to
initiate the communication with the remote processor, so to be able to initiate
the service (ns announcement sent to the remote processor).
This implies that:
-either the RPMsg device has been probed first by a remote ns announcement or by
a Linux kernel driver using the "driver_override", to register an auxiliary
device. In this case an endpoint will be created associated to the RPMsg service
- or create a RPMsg device on first ioctl endpoint creation request, if it does
not exist (that could trig a NS announcement to remote processor).

But I'm not sure that this approach would work with QCOM RPMsg backends...

>
> I'm out of time for today - I will continue tomorrow.

It seems to me that the main point to step forward is to clarify the global
design and features of the rpmsg-ctrl.
Depending on the decision taken, this series could be trashed and rewritten from
a blank page...To not lost to much time on the series don't hesitate to limit
the review to the minimum.

Thanks,
Arnaud

>
> Thanks,
> Mathieu
>
>> + return NULL;
>> +}
>> +
>> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
>> unsigned long arg)
>> {
>> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
>> -
>> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
>> + void __user *argp = (void __user *)arg;
>> + struct rpmsg_channel_info chinfo;
>> + struct rpmsg_endpoint_info eptinfo;
>> + struct rpmsg_device *newch;
>> +
>> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
>> + return -EINVAL;
>> +
>> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
>> + return -EFAULT;
>> +
>> + /*
>> + * In a frst step only the rpmsg_raw service is supported.
>> + * The override is foorced to RPMSG_RAW_SERVICE
>> + */
>> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
>> + if (!chinfo.driver_override)
>> + return -ENODEV;
>> +
>> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
>> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
>> + chinfo.src = eptinfo.src;
>> + chinfo.dst = eptinfo.dst;
>> +
>> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
>> + if (!newch) {
>> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
>> + return -ENXIO;
>> + }
>>
>> return 0;
>> };
>> --
>> 2.17.1
>>

2021-01-22 21:04:00

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

On Fri, Jan 22, 2021 at 02:05:27PM +0100, Arnaud POULIQUEN wrote:
> Hi Mathieu,
>
> On 1/22/21 12:52 AM, Mathieu Poirier wrote:
> > On Tue, Dec 22, 2020 at 11:57:14AM +0100, Arnaud Pouliquen wrote:
> >> Implement the ioctl function that parses the list of
> >> rpmsg drivers registered to create an associated device.
> >> To be ISO user API, in a first step, the driver_override
> >> is only allowed for the RPMsg raw service, supported by the
> >> rpmsg_char driver.
> >>
> >> Signed-off-by: Arnaud Pouliquen <[email protected]>
> >> ---
> >> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
> >> 1 file changed, 41 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
> >> index 065e2e304019..8381b5b2b794 100644
> >> --- a/drivers/rpmsg/rpmsg_ctrl.c
> >> +++ b/drivers/rpmsg/rpmsg_ctrl.c
> >> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
> >> return 0;
> >> }
> >>
> >> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
> >> +{
> >> + struct rpmsg_ctl_info *drv_info;
> >> +
> >> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
> >> + if (drv_info->ctrl->service == service)
> >> + return drv_info->ctrl->drv_name;
> >> + }
> >> +
> >
> > I'm unsure about the above... To me this looks like what the .match() function
> > of a bus would do. And when I read Bjorn's comment he brought up the
> > auxiliary_bus. I don't know about the auxiliary_bus but it is worth looking
> > into. Registering with a bus would streamline a lot of the code in this
> > patchset.
>
> As answered Bjorn, we already have the RPMsg bus to manage the rpmsg devices.
> Look like duplication from my POV, except if the IOCTL does not manage channel
> but only endpoint.
>
> In my design I considered that the rpmsg_ctrl creates a channel associated to a
> rpmsg_device such as the RPMsg ns_announcement.
>
> Based on this assumption, if we implement the auxiliary_bus (or other) for the
> rpmsg_ctrl a RPMsg driver will have to manage the probe by rpmsg_bus and by the
> auxillary bus. The probe from the auxiliary bus would lead to the creation of an
> RPMsg device on the rpmsg_bus, so a duplication with cross dependencies and
> would probably make tricky the remove part.
>
> That said, I think the design depends on the functionality that should be
> implemented in the rpmsg_ctrl. Here is an alternative approach based on the
> auxiliary bus, which I'm starting to think about:
>
> The current approach of the rpmsg_char driver is to use the IOCTRL interface to
> instantiate a cdev with an endpoint (the RPMsg device is associated with the
> ioctl dev). This would correspond to the use of an auxiliary bus to manage local
> endpoint creations.
>
> We could therefore consider an RPMsg name service based on an RPmsg device. This
> RPMsg device would register a kind of "RPMsg service endpoint" driver on the
> auxiliary rpmsg_ioctl bus.
> The rpmsg_ctrl will be used to instantiate the endpoints for this RPMsg device.
> on user application request the rpmsg_ctrl will call the appropriate auxiliary
> device to create an endpoint.
>
> If we consider that one objective of this series is to allow application to
> initiate the communication with the remote processor, so to be able to initiate
> the service (ns announcement sent to the remote processor).
> This implies that:
> -either the RPMsg device has been probed first by a remote ns announcement or by
> a Linux kernel driver using the "driver_override", to register an auxiliary
> device. In this case an endpoint will be created associated to the RPMsg service
> - or create a RPMsg device on first ioctl endpoint creation request, if it does
> not exist (that could trig a NS announcement to remote processor).
>
> But I'm not sure that this approach would work with QCOM RPMsg backends...
>

I don't think there is a way forward with this set without a clear understanding
of the Glink and SMD drivers. I have already spent a fair amount of time in the
Glink driver and will continue on Monday with SMD.

> >
> > I'm out of time for today - I will continue tomorrow.
>
> It seems to me that the main point to step forward is to clarify the global
> design and features of the rpmsg-ctrl.
> Depending on the decision taken, this series could be trashed and rewritten from
> a blank page...To not lost to much time on the series don't hesitate to limit
> the review to the minimum.
>

I doubt you will ever get clear guidelines on the whole solution. I will get
back to you once I am done with the SMD driver, which should be in the
latter part of next week.

> Thanks,
> Arnaud
>
> >
> > Thanks,
> > Mathieu
> >
> >> + return NULL;
> >> +}
> >> +
> >> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
> >> unsigned long arg)
> >> {
> >> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
> >> -
> >> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
> >> + void __user *argp = (void __user *)arg;
> >> + struct rpmsg_channel_info chinfo;
> >> + struct rpmsg_endpoint_info eptinfo;
> >> + struct rpmsg_device *newch;
> >> +
> >> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> >> + return -EINVAL;
> >> +
> >> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> >> + return -EFAULT;
> >> +
> >> + /*
> >> + * In a frst step only the rpmsg_raw service is supported.
> >> + * The override is foorced to RPMSG_RAW_SERVICE
> >> + */
> >> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
> >> + if (!chinfo.driver_override)
> >> + return -ENODEV;
> >> +
> >> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> >> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
> >> + chinfo.src = eptinfo.src;
> >> + chinfo.dst = eptinfo.dst;
> >> +
> >> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
> >> + if (!newch) {
> >> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
> >> + return -ENXIO;
> >> + }
> >>
> >> return 0;
> >> };
> >> --
> >> 2.17.1
> >>

2021-01-26 06:03:51

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

Hi Mathieu,

On 1/22/21 9:59 PM, Mathieu Poirier wrote:
> On Fri, Jan 22, 2021 at 02:05:27PM +0100, Arnaud POULIQUEN wrote:
>> Hi Mathieu,
>>
>> On 1/22/21 12:52 AM, Mathieu Poirier wrote:
>>> On Tue, Dec 22, 2020 at 11:57:14AM +0100, Arnaud Pouliquen wrote:
>>>> Implement the ioctl function that parses the list of
>>>> rpmsg drivers registered to create an associated device.
>>>> To be ISO user API, in a first step, the driver_override
>>>> is only allowed for the RPMsg raw service, supported by the
>>>> rpmsg_char driver.
>>>>
>>>> Signed-off-by: Arnaud Pouliquen <[email protected]>
>>>> ---
>>>> drivers/rpmsg/rpmsg_ctrl.c | 43 ++++++++++++++++++++++++++++++++++++--
>>>> 1 file changed, 41 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
>>>> index 065e2e304019..8381b5b2b794 100644
>>>> --- a/drivers/rpmsg/rpmsg_ctrl.c
>>>> +++ b/drivers/rpmsg/rpmsg_ctrl.c
>>>> @@ -56,12 +56,51 @@ static int rpmsg_ctrl_dev_open(struct inode *inode, struct file *filp)
>>>> return 0;
>>>> }
>>>>
>>>> +static const char *rpmsg_ctrl_get_drv_name(u32 service)
>>>> +{
>>>> + struct rpmsg_ctl_info *drv_info;
>>>> +
>>>> + list_for_each_entry(drv_info, &rpmsg_drv_list, node) {
>>>> + if (drv_info->ctrl->service == service)
>>>> + return drv_info->ctrl->drv_name;
>>>> + }
>>>> +
>>>
>>> I'm unsure about the above... To me this looks like what the .match() function
>>> of a bus would do. And when I read Bjorn's comment he brought up the
>>> auxiliary_bus. I don't know about the auxiliary_bus but it is worth looking
>>> into. Registering with a bus would streamline a lot of the code in this
>>> patchset.
>>
>> As answered Bjorn, we already have the RPMsg bus to manage the rpmsg devices.
>> Look like duplication from my POV, except if the IOCTL does not manage channel
>> but only endpoint.
>>
>> In my design I considered that the rpmsg_ctrl creates a channel associated to a
>> rpmsg_device such as the RPMsg ns_announcement.
>>
>> Based on this assumption, if we implement the auxiliary_bus (or other) for the
>> rpmsg_ctrl a RPMsg driver will have to manage the probe by rpmsg_bus and by the
>> auxillary bus. The probe from the auxiliary bus would lead to the creation of an
>> RPMsg device on the rpmsg_bus, so a duplication with cross dependencies and
>> would probably make tricky the remove part.
>>
>> That said, I think the design depends on the functionality that should be
>> implemented in the rpmsg_ctrl. Here is an alternative approach based on the
>> auxiliary bus, which I'm starting to think about:
>>
>> The current approach of the rpmsg_char driver is to use the IOCTRL interface to
>> instantiate a cdev with an endpoint (the RPMsg device is associated with the
>> ioctl dev). This would correspond to the use of an auxiliary bus to manage local
>> endpoint creations.
>>
>> We could therefore consider an RPMsg name service based on an RPmsg device. This
>> RPMsg device would register a kind of "RPMsg service endpoint" driver on the
>> auxiliary rpmsg_ioctl bus.
>> The rpmsg_ctrl will be used to instantiate the endpoints for this RPMsg device.
>> on user application request the rpmsg_ctrl will call the appropriate auxiliary
>> device to create an endpoint.
>>
>> If we consider that one objective of this series is to allow application to
>> initiate the communication with the remote processor, so to be able to initiate
>> the service (ns announcement sent to the remote processor).
>> This implies that:
>> -either the RPMsg device has been probed first by a remote ns announcement or by
>> a Linux kernel driver using the "driver_override", to register an auxiliary
>> device. In this case an endpoint will be created associated to the RPMsg service
>> - or create a RPMsg device on first ioctl endpoint creation request, if it does
>> not exist (that could trig a NS announcement to remote processor).
>>
>> But I'm not sure that this approach would work with QCOM RPMsg backends...
>>
>
> I don't think there is a way forward with this set without a clear understanding
> of the Glink and SMD drivers. I have already spent a fair amount of time in the
> Glink driver and will continue on Monday with SMD.
>
>>>
>>> I'm out of time for today - I will continue tomorrow.
>>
>> It seems to me that the main point to step forward is to clarify the global
>> design and features of the rpmsg-ctrl.
>> Depending on the decision taken, this series could be trashed and rewritten from
>> a blank page...To not lost to much time on the series don't hesitate to limit
>> the review to the minimum.
>>
>
> I doubt you will ever get clear guidelines on the whole solution. I will get
> back to you once I am done with the SMD driver, which should be in the
> latter part of next week.


Thanks for your time past on this topic!

I don't expect a clear guidance but that we clarify the objective of this RPMsg
IOCTL. A first step would be sure that we are in line with the objective of the
RPMsg IOCTL.
For instance should we continue in a way to have the rpmsg_char more "rpmsg
service" generic, relying on a rpmsg_ioctl for the control part? Or should we
implement something independent (with is own API) to limit dependency with QCOM
backends constraints?
At the end, if implementing a IOCTL interface directly in the RPMsg TTY seems to
you and Bjorn simpler, I can also go on this way...

On my side I expect to find time this week to prototype a RPMSg ioctl using the
auxiliary bus to better understand involved mechanism.

Thanks,
Arnaud

>
>> Thanks,
>> Arnaud
>>
>>>
>>> Thanks,
>>> Mathieu
>>>
>>>> + return NULL;
>>>> +}
>>>> +
>>>> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
>>>> unsigned long arg)
>>>> {
>>>> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
>>>> -
>>>> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
>>>> + void __user *argp = (void __user *)arg;
>>>> + struct rpmsg_channel_info chinfo;
>>>> + struct rpmsg_endpoint_info eptinfo;
>>>> + struct rpmsg_device *newch;
>>>> +
>>>> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
>>>> + return -EINVAL;
>>>> +
>>>> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
>>>> + return -EFAULT;
>>>> +
>>>> + /*
>>>> + * In a frst step only the rpmsg_raw service is supported.
>>>> + * The override is foorced to RPMSG_RAW_SERVICE
>>>> + */
>>>> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
>>>> + if (!chinfo.driver_override)
>>>> + return -ENODEV;
>>>> +
>>>> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
>>>> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
>>>> + chinfo.src = eptinfo.src;
>>>> + chinfo.dst = eptinfo.dst;
>>>> +
>>>> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
>>>> + if (!newch) {
>>>> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
>>>> + return -ENXIO;
>>>> + }
>>>>
>>>> return 0;
>>>> };
>>>> --
>>>> 2.17.1
>>>>

2021-01-29 00:16:23

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device

[...]

> > It seems to me that the main point to step forward is to clarify the global
> > design and features of the rpmsg-ctrl.
> > Depending on the decision taken, this series could be trashed and rewritten from
> > a blank page...To not lost to much time on the series don't hesitate to limit
> > the review to the minimum.
> >
>
> I doubt you will ever get clear guidelines on the whole solution. I will get
> back to you once I am done with the SMD driver, which should be in the
> latter part of next week.
>

After looking at the rpmsg_chrdev driver, its current customers (i.e the Qcom
drivers), the rpmsg name service and considering the long term goals of this
patchset I have the following guidelines:

1) I thought long and hard about how to split the current rpmsg_chrdev driver
between the control plane and the raw device plane and the end solution looks
much slimpler than I expected. Exporting function rpmsg_eptdev_create() after
moving it to another file (along with other dependencies) should be all we need.
Calling rpmsg_eptdev_create() from rpmsg_ctrldev_ioctl() will automatically load
the new driver, the same way calling rpmsg_ns_register_device() from
rpmsg_probe() took care of loading the rpmsg_ns driver.

2) While keeping the control plane functionality related to
RPMSG_CREATE_EPT_IOCTL intact, introduce a new RPMSG_CREATE_DEV_IOCTL that will
allow for the instantiation of rpmsg_devices, exactly the same way a name service
announcement from a remote processor does. I envision that code path to
eventually call rpmsg_create_channel().

3) Leave the rpmsg_channel_info structure intact and use the
rpmsg_channel_info::name to bind to a rpmsg_driver, exactly how it is currently
done for name service driver selection. That will allow us to re-use the
current rpmsg_bus intrastructure, i.e rpmsg_bus::match(), without having to deal
with yet another bus type. Proceeding this way gives us the opportunity to keep
the current channel name convention for other rpmch_chrdev users untouched.

4) In a prior conversation you indicated the intention of instantiating the
rpmsg_chrdev from the name service interface. I agree with doing so but
conjugating that with the RPMSG_CHAR kenrel define may be tricky. I will wait
to see what you come up with.

I hope this helps.

Thanks,
Mathieu



> > Thanks,
> > Arnaud
> >
> > >
> > > Thanks,
> > > Mathieu
> > >
> > >> + return NULL;
> > >> +}
> > >> +
> > >> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
> > >> unsigned long arg)
> > >> {
> > >> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
> > >> -
> > >> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
> > >> + void __user *argp = (void __user *)arg;
> > >> + struct rpmsg_channel_info chinfo;
> > >> + struct rpmsg_endpoint_info eptinfo;
> > >> + struct rpmsg_device *newch;
> > >> +
> > >> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> > >> + return -EINVAL;
> > >> +
> > >> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> > >> + return -EFAULT;
> > >> +
> > >> + /*
> > >> + * In a frst step only the rpmsg_raw service is supported.
> > >> + * The override is foorced to RPMSG_RAW_SERVICE
> > >> + */
> > >> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
> > >> + if (!chinfo.driver_override)
> > >> + return -ENODEV;
> > >> +
> > >> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> > >> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
> > >> + chinfo.src = eptinfo.src;
> > >> + chinfo.dst = eptinfo.dst;
> > >> +
> > >> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
> > >> + if (!newch) {
> > >> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
> > >> + return -ENXIO;
> > >> + }
> > >>
> > >> return 0;
> > >> };
> > >> --
> > >> 2.17.1
> > >>

2021-01-29 12:17:50

by Arnaud Pouliquen

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] rpmsg: ctrl: implement the ioctl function to create device



On 1/29/21 1:13 AM, Mathieu Poirier wrote:
> [...]
>
>>> It seems to me that the main point to step forward is to clarify the global
>>> design and features of the rpmsg-ctrl.
>>> Depending on the decision taken, this series could be trashed and rewritten from
>>> a blank page...To not lost to much time on the series don't hesitate to limit
>>> the review to the minimum.
>>>
>>
>> I doubt you will ever get clear guidelines on the whole solution. I will get
>> back to you once I am done with the SMD driver, which should be in the
>> latter part of next week.
>>
>
> After looking at the rpmsg_chrdev driver, its current customers (i.e the Qcom
> drivers), the rpmsg name service and considering the long term goals of this
> patchset I have the following guidelines:
>
> 1) I thought long and hard about how to split the current rpmsg_chrdev driver
> between the control plane and the raw device plane and the end solution looks
> much slimpler than I expected. Exporting function rpmsg_eptdev_create() after
> moving it to another file (along with other dependencies) should be all we need.
> Calling rpmsg_eptdev_create() from rpmsg_ctrldev_ioctl() will automatically load
> the new driver, the same way calling rpmsg_ns_register_device() from
> rpmsg_probe() took care of loading the rpmsg_ns driver.
>
> 2) While keeping the control plane functionality related to
> RPMSG_CREATE_EPT_IOCTL intact, introduce a new RPMSG_CREATE_DEV_IOCTL that will
> allow for the instantiation of rpmsg_devices, exactly the same way a name service
> announcement from a remote processor does. I envision that code path to
> eventually call rpmsg_create_channel().
>
> 3) Leave the rpmsg_channel_info structure intact and use the
> rpmsg_channel_info::name to bind to a rpmsg_driver, exactly how it is currently
> done for name service driver selection. That will allow us to re-use the
> current rpmsg_bus intrastructure, i.e rpmsg_bus::match(), without having to deal
> with yet another bus type. Proceeding this way gives us the opportunity to keep
> the current channel name convention for other rpmch_chrdev users untouched.
>
> 4) In a prior conversation you indicated the intention of instantiating the
> rpmsg_chrdev from the name service interface. I agree with doing so but
> conjugating that with the RPMSG_CHAR kenrel define may be tricky. I will wait
> to see what you come up with.
>
> I hope this helps.

Thank you for these guidelines! It need a bit of time to look at the details
(especially point 1) ), but your suggestion seems to me to be a good compromise.
I hope to come back soon with a new revision based on this point.

Regards,
Arnaud

>
> Thanks,
> Mathieu
>
>
>
>>> Thanks,
>>> Arnaud
>>>
>>>>
>>>> Thanks,
>>>> Mathieu
>>>>
>>>>> + return NULL;
>>>>> +}
>>>>> +
>>>>> static long rpmsg_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
>>>>> unsigned long arg)
>>>>> {
>>>>> struct rpmsg_ctrl_dev *ctrldev = fp->private_data;
>>>>> -
>>>>> - dev_info(&ctrldev->dev, "Control not yet implemented\n");
>>>>> + void __user *argp = (void __user *)arg;
>>>>> + struct rpmsg_channel_info chinfo;
>>>>> + struct rpmsg_endpoint_info eptinfo;
>>>>> + struct rpmsg_device *newch;
>>>>> +
>>>>> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
>>>>> + return -EINVAL;
>>>>> +
>>>>> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
>>>>> + return -EFAULT;
>>>>> +
>>>>> + /*
>>>>> + * In a frst step only the rpmsg_raw service is supported.
>>>>> + * The override is foorced to RPMSG_RAW_SERVICE
>>>>> + */
>>>>> + chinfo.driver_override = rpmsg_ctrl_get_drv_name(RPMSG_RAW_SERVICE);
>>>>> + if (!chinfo.driver_override)
>>>>> + return -ENODEV;
>>>>> +
>>>>> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
>>>>> + chinfo.name[RPMSG_NAME_SIZE - 1] = '\0';
>>>>> + chinfo.src = eptinfo.src;
>>>>> + chinfo.dst = eptinfo.dst;
>>>>> +
>>>>> + newch = rpmsg_create_channel(ctrldev->rpdev, &chinfo);
>>>>> + if (!newch) {
>>>>> + dev_err(&ctrldev->dev, "rpmsg_create_channel failed\n");
>>>>> + return -ENXIO;
>>>>> + }
>>>>>
>>>>> return 0;
>>>>> };
>>>>> --
>>>>> 2.17.1
>>>>>