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

From: Bjorn Andersson
Date: Mon Jan 04 2021 - 20:34:05 EST


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 <arnaud.pouliquen@xxxxxxxxxxx>
> ---
> 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
>