On Tue, Mar 23, 2021 at 01:27:35PM +0100, Arnaud Pouliquen wrote:
> A rpmsg char device allows to probe the endpoint device on a remote name
> service announcement.
> 
> With this patch the /dev/rpmsgX interface is created either by a user
> application or by the remote firmware.
> 
> Signed-off-by: Arnaud Pouliquen <[email protected]>
> ---
>  drivers/rpmsg/rpmsg_char.c | 58 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 57 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> index 7f6d46078179..69e774edb74b 100644
> --- a/drivers/rpmsg/rpmsg_char.c
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -28,6 +28,8 @@
>  
>  #define RPMSG_DEV_MAX        (MINORMASK + 1)
>  
> +#define RPMSG_CHAR_DEVNAME "rpmsg-raw"
> +
>  static dev_t rpmsg_major;
>  
>  static DEFINE_IDA(rpmsg_ept_ida);
> @@ -405,13 +407,67 @@ int rpmsg_chrdev_create_eptdev(struct rpmsg_device 
> *rpdev, struct device *parent
>  }
>  EXPORT_SYMBOL(rpmsg_chrdev_create_eptdev);
>  
> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> +{
> +     struct rpmsg_channel_info chinfo;
> +     struct rpmsg_eptdev *eptdev;
> +
> +     if (!rpdev->ept)
> +             return -EINVAL;
> +
> +     memcpy(chinfo.name, RPMSG_CHAR_DEVNAME, sizeof(RPMSG_CHAR_DEVNAME));
> +     chinfo.src = rpdev->src;
> +     chinfo.dst = rpdev->dst;
> +
> +     eptdev = __rpmsg_chrdev_create_eptdev(rpdev, &rpdev->dev, chinfo, NULL);
> +     if (IS_ERR(eptdev))
> +             return PTR_ERR(eptdev);
> +
> +     /* Set the private field of the default endpoint to retrieve context on 
> callback. */
> +     rpdev->ept->priv = eptdev;
> +
> +     return 0;
> +}
> +
> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> +{
> +     int ret;
> +
> +     ret = device_for_each_child(&rpdev->dev, NULL, 
> rpmsg_chrdev_destroy_eptdev);
> +     if (ret)
> +             dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret);
> +}
> +
> +static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
> +     { .name = RPMSG_CHAR_DEVNAME },
> +     { },
> +};
> +
> +static struct rpmsg_driver rpmsg_chrdev_driver = {
> +     .probe = rpmsg_chrdev_probe,
> +     .remove = rpmsg_chrdev_remove,
> +     .id_table = rpmsg_chrdev_id_table,
> +     .callback = rpmsg_ept_cb,
> +     .drv = {
> +             .name = "rpmsg_chrdev",
> +     },
> +};
> +
>  static int rpmsg_chrdev_init(void)
>  {
>       int ret;
>  
>       ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
> -     if (ret < 0)
> +     if (ret < 0) {
>               pr_err("rpmsg: failed to allocate char dev region\n");
> +             return ret;
> +     }
> +
> +     ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> +     if (ret < 0) {
> +             pr_err("rpmsg: failed to register rpmsg raw driver\n");
> +             unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +     }

Function unregister_rpmsg_driver() has to be called in rpmsg_chrdev_exit().

>  
>       return ret;
>  }
> -- 
> 2.17.1
> 

Reply via email to