diff mbox series

[v2,02/16] rpmsg: add RPMsg control API to register service

Message ID 20201222105726.16906-3-arnaud.pouliquen@foss.st.com
State New
Headers show
Series introduce generic IOCTL interface for RPMsg channels management | expand

Commit Message

Arnaud POULIQUEN Dec. 22, 2020, 10:57 a.m. UTC
Add API to register a RPMsg service to the control device.
The rpmsg_drv_ctrl_info structure links a service to its driver.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/rpmsg/rpmsg_ctrl.c | 57 ++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg.h      | 31 +++++++++++++++++++++
 include/uapi/linux/rpmsg.h | 14 ++++++++++
 3 files changed, 102 insertions(+)

Comments

Bjorn Andersson Jan. 5, 2021, 12:34 a.m. UTC | #1
On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

> Add API to register a RPMsg service to the control device.

> The rpmsg_drv_ctrl_info structure links a service to its driver.

> 

> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>

> ---

>  drivers/rpmsg/rpmsg_ctrl.c | 57 ++++++++++++++++++++++++++++++++++++++

>  include/linux/rpmsg.h      | 31 +++++++++++++++++++++

>  include/uapi/linux/rpmsg.h | 14 ++++++++++

>  3 files changed, 102 insertions(+)

> 

> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c

> index 425c3e32ada4..065e2e304019 100644

> --- a/drivers/rpmsg/rpmsg_ctrl.c

> +++ b/drivers/rpmsg/rpmsg_ctrl.c

> @@ -27,6 +27,20 @@ struct rpmsg_ctrl_dev {

>  	struct device dev;

>  };

>  

> +/**

> + * struct rpmsg_ctl_info - control info list node

> + * @ctrl:	control driver info

> + * @node:	list node

> + *

> + * This structure is used by rpmsg_ctl to list the registered drivers services

> + */

> +struct rpmsg_ctl_info {

> +	const struct rpmsg_drv_ctrl_info *ctrl;

> +	struct list_head node;

> +};

> +

> +static LIST_HEAD(rpmsg_drv_list);

> +

>  static DEFINE_IDA(rpmsg_ctrl_ida);

>  static DEFINE_IDA(rpmsg_minor_ida);

>  

> @@ -175,6 +189,49 @@ static struct rpmsg_driver rpmsg_ctrl_driver = {

>  	.remove = rpmsg_ctrl_remove,

>  };

>  

> +/**

> + * rpmsg_ctrl_register_ctl() -register control for the associated service

> + * @ctrl: rpmsg driver information

> + *

> + * This function is called by the rpmsg driver to register a service that will

> + * be exposed to be instantiate by the application.

> + */

> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +	struct rpmsg_ctl_info *drv_info;

> +

> +	drv_info =  kzalloc(sizeof(*drv_info), GFP_KERNEL);

> +	if (!drv_info)

> +		return -ENOMEM;

> +

> +	drv_info->ctrl = ctrl;

> +

> +	list_add_tail(&drv_info->node, &rpmsg_drv_list);

> +

> +	return 0;

> +}

> +EXPORT_SYMBOL(rpmsg_ctrl_register_ctl);

> +

> +/**

> + * rpmsg_ctrl_unregister_ctl() -unregister control for the associated service

> + * @ctrl: the rpmsg control information

> + *

> + * This function is called by the rpmsg driver to unregister the associated

> + * service.

> + */

> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +	struct rpmsg_ctl_info *drv_info, *tmp;

> +

> +	list_for_each_entry_safe(drv_info, tmp, &rpmsg_drv_list, node) {

> +		if (drv_info->ctrl == ctrl) {

> +			list_del(&drv_info->node);

> +			kfree(drv_info);

> +		}

> +	}

> +}

> +EXPORT_SYMBOL(rpmsg_ctrl_unregister_ctl);

> +

>  static int rpmsg_ctrl_init(void)

>  {

>  	int ret;

> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h

> index a5db828b2420..5d64704c2346 100644

> --- a/include/linux/rpmsg.h

> +++ b/include/linux/rpmsg.h

> @@ -26,6 +26,19 @@ struct rpmsg_endpoint;

>  struct rpmsg_device_ops;

>  struct rpmsg_endpoint_ops;

>  

> +/**

> + * struct rpmsg_drv_ctrl_info - rpmsg ctrl structure

> + * @drv_name:	name of the associated driver

> + * @service:	the associated rpmsg service listed in @rpmsg_services

> + *

> + * This structure is used by rpmsg_ctl to link the endpoint creation to the

> + * service rpmsg driver.

> + */

> +struct rpmsg_drv_ctrl_info {

> +	const char *drv_name;

> +	u32  service;

> +};

> +

>  /**

>   * struct rpmsg_channel_info - channel info representation

>   * @name: name of service

> @@ -315,4 +328,22 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,

>  	module_driver(__rpmsg_driver, register_rpmsg_driver, \

>  			unregister_rpmsg_driver)

>  

> +#if IS_ENABLED(CONFIG_RPMSG_CTRL)

> +

> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

> +

> +#else

> +

> +static inline int rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +	return 0;

> +}

> +

> +static inline void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +}

> +

> +#endif /* IS_ENABLED(CONFIG_RPMSG_CTRL) */

> +

>  #endif /* _LINUX_RPMSG_H */

> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h

> index e14c6dab4223..0b0cb028e0b3 100644

> --- a/include/uapi/linux/rpmsg.h

> +++ b/include/uapi/linux/rpmsg.h

> @@ -9,6 +9,20 @@

>  #include <linux/ioctl.h>

>  #include <linux/types.h>

>  

> +/**

> + * enum rpmsg_services - list of supported RPMsg services

> + *

> + * @RPMSG_RAW_SERVICE: char device RPMSG service

> + * @RPMSG_START_PRIVATE_SERVICES: private services have to be declared after.

> + */

> +enum rpmsg_services {

> +	/* Reserved services */

> +	RPMSG_RAW_SERVICE =  0,

> +


What kind of things do you envision this list to contain in a year from
now?

Regards,
Bjorn

> +	/* Private services */

> +	RPMSG_START_PRIVATE_SERVICES =  1024,

> +};

> +

>  /**

>   * struct rpmsg_endpoint_info - endpoint info representation

>   * @name: name of service

> -- 

> 2.17.1

>
Arnaud POULIQUEN Jan. 5, 2021, 4:53 p.m. UTC | #2
On 1/5/21 1:34 AM, Bjorn Andersson wrote:
> On Tue 22 Dec 04:57 CST 2020, Arnaud Pouliquen wrote:

> 

>> Add API to register a RPMsg service to the control device.

>> The rpmsg_drv_ctrl_info structure links a service to its driver.

>>

>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>

>> ---

>>  drivers/rpmsg/rpmsg_ctrl.c | 57 ++++++++++++++++++++++++++++++++++++++

>>  include/linux/rpmsg.h      | 31 +++++++++++++++++++++

>>  include/uapi/linux/rpmsg.h | 14 ++++++++++

>>  3 files changed, 102 insertions(+)

>>

>> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c

>> index 425c3e32ada4..065e2e304019 100644

>> --- a/drivers/rpmsg/rpmsg_ctrl.c

>> +++ b/drivers/rpmsg/rpmsg_ctrl.c

>> @@ -27,6 +27,20 @@ struct rpmsg_ctrl_dev {

>>  	struct device dev;

>>  };

>>  

>> +/**

>> + * struct rpmsg_ctl_info - control info list node

>> + * @ctrl:	control driver info

>> + * @node:	list node

>> + *

>> + * This structure is used by rpmsg_ctl to list the registered drivers services

>> + */

>> +struct rpmsg_ctl_info {

>> +	const struct rpmsg_drv_ctrl_info *ctrl;

>> +	struct list_head node;

>> +};

>> +

>> +static LIST_HEAD(rpmsg_drv_list);

>> +

>>  static DEFINE_IDA(rpmsg_ctrl_ida);

>>  static DEFINE_IDA(rpmsg_minor_ida);

>>  

>> @@ -175,6 +189,49 @@ static struct rpmsg_driver rpmsg_ctrl_driver = {

>>  	.remove = rpmsg_ctrl_remove,

>>  };

>>  

>> +/**

>> + * rpmsg_ctrl_register_ctl() -register control for the associated service

>> + * @ctrl: rpmsg driver information

>> + *

>> + * This function is called by the rpmsg driver to register a service that will

>> + * be exposed to be instantiate by the application.

>> + */

>> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

>> +{

>> +	struct rpmsg_ctl_info *drv_info;

>> +

>> +	drv_info =  kzalloc(sizeof(*drv_info), GFP_KERNEL);

>> +	if (!drv_info)

>> +		return -ENOMEM;

>> +

>> +	drv_info->ctrl = ctrl;

>> +

>> +	list_add_tail(&drv_info->node, &rpmsg_drv_list);

>> +

>> +	return 0;

>> +}

>> +EXPORT_SYMBOL(rpmsg_ctrl_register_ctl);

>> +

>> +/**

>> + * rpmsg_ctrl_unregister_ctl() -unregister control for the associated service

>> + * @ctrl: the rpmsg control information

>> + *

>> + * This function is called by the rpmsg driver to unregister the associated

>> + * service.

>> + */

>> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

>> +{

>> +	struct rpmsg_ctl_info *drv_info, *tmp;

>> +

>> +	list_for_each_entry_safe(drv_info, tmp, &rpmsg_drv_list, node) {

>> +		if (drv_info->ctrl == ctrl) {

>> +			list_del(&drv_info->node);

>> +			kfree(drv_info);

>> +		}

>> +	}

>> +}

>> +EXPORT_SYMBOL(rpmsg_ctrl_unregister_ctl);

>> +

>>  static int rpmsg_ctrl_init(void)

>>  {

>>  	int ret;

>> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h

>> index a5db828b2420..5d64704c2346 100644

>> --- a/include/linux/rpmsg.h

>> +++ b/include/linux/rpmsg.h

>> @@ -26,6 +26,19 @@ struct rpmsg_endpoint;

>>  struct rpmsg_device_ops;

>>  struct rpmsg_endpoint_ops;

>>  

>> +/**

>> + * struct rpmsg_drv_ctrl_info - rpmsg ctrl structure

>> + * @drv_name:	name of the associated driver

>> + * @service:	the associated rpmsg service listed in @rpmsg_services

>> + *

>> + * This structure is used by rpmsg_ctl to link the endpoint creation to the

>> + * service rpmsg driver.

>> + */

>> +struct rpmsg_drv_ctrl_info {

>> +	const char *drv_name;

>> +	u32  service;

>> +};

>> +

>>  /**

>>   * struct rpmsg_channel_info - channel info representation

>>   * @name: name of service

>> @@ -315,4 +328,22 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,

>>  	module_driver(__rpmsg_driver, register_rpmsg_driver, \

>>  			unregister_rpmsg_driver)

>>  

>> +#if IS_ENABLED(CONFIG_RPMSG_CTRL)

>> +

>> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

>> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

>> +

>> +#else

>> +

>> +static inline int rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

>> +{

>> +	return 0;

>> +}

>> +

>> +static inline void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

>> +{

>> +}

>> +

>> +#endif /* IS_ENABLED(CONFIG_RPMSG_CTRL) */

>> +

>>  #endif /* _LINUX_RPMSG_H */

>> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h

>> index e14c6dab4223..0b0cb028e0b3 100644

>> --- a/include/uapi/linux/rpmsg.h

>> +++ b/include/uapi/linux/rpmsg.h

>> @@ -9,6 +9,20 @@

>>  #include <linux/ioctl.h>

>>  #include <linux/types.h>

>>  

>> +/**

>> + * enum rpmsg_services - list of supported RPMsg services

>> + *

>> + * @RPMSG_RAW_SERVICE: char device RPMSG service

>> + * @RPMSG_START_PRIVATE_SERVICES: private services have to be declared after.

>> + */

>> +enum rpmsg_services {

>> +	/* Reserved services */

>> +	RPMSG_RAW_SERVICE =  0,

>> +

> 

> What kind of things do you envision this list to contain in a year from

> now?


The next one is the TTY, and perhaps the RPMsg I2C that allows to share a I2C
bus between the main and a remote processor.

Please notice that this field will also has to be added in a second step to the
rpmsg_endpoint_info struct, to allow the applications to select the expected
service.

Regards
Arnaud

> 

> Regards,

> Bjorn

> 

>> +	/* Private services */

>> +	RPMSG_START_PRIVATE_SERVICES =  1024,

>> +};

>> +

>>  /**

>>   * struct rpmsg_endpoint_info - endpoint info representation

>>   * @name: name of service

>> -- 

>> 2.17.1

>>
Mathieu Poirier Jan. 21, 2021, 11:46 p.m. UTC | #3
On Tue, Dec 22, 2020 at 11:57:12AM +0100, Arnaud Pouliquen wrote:
> Add API to register a RPMsg service to the control device.

> The rpmsg_drv_ctrl_info structure links a service to its driver.

> 

> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>

> ---

>  drivers/rpmsg/rpmsg_ctrl.c | 57 ++++++++++++++++++++++++++++++++++++++

>  include/linux/rpmsg.h      | 31 +++++++++++++++++++++

>  include/uapi/linux/rpmsg.h | 14 ++++++++++

>  3 files changed, 102 insertions(+)

> 

> diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c

> index 425c3e32ada4..065e2e304019 100644

> --- a/drivers/rpmsg/rpmsg_ctrl.c

> +++ b/drivers/rpmsg/rpmsg_ctrl.c

> @@ -27,6 +27,20 @@ struct rpmsg_ctrl_dev {

>  	struct device dev;

>  };

>  

> +/**

> + * struct rpmsg_ctl_info - control info list node

> + * @ctrl:	control driver info

> + * @node:	list node

> + *

> + * This structure is used by rpmsg_ctl to list the registered drivers services

> + */

> +struct rpmsg_ctl_info {


struct rpmsg_ctrl_info

> +	const struct rpmsg_drv_ctrl_info *ctrl;

> +	struct list_head node;

> +};

> +

> +static LIST_HEAD(rpmsg_drv_list);

> +

>  static DEFINE_IDA(rpmsg_ctrl_ida);

>  static DEFINE_IDA(rpmsg_minor_ida);

>  

> @@ -175,6 +189,49 @@ static struct rpmsg_driver rpmsg_ctrl_driver = {

>  	.remove = rpmsg_ctrl_remove,

>  };

>  

> +/**

> + * rpmsg_ctrl_register_ctl() -register control for the associated service

> + * @ctrl: rpmsg driver information

> + *

> + * This function is called by the rpmsg driver to register a service that will

> + * be exposed to be instantiate by the application.

> + */

> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)


Here an rpmsg_drv is registered with the infrastructure and as such I propose
rpmsg_ctrl_register_driver_ctrl().

> +{

> +	struct rpmsg_ctl_info *drv_info;

> +

> +	drv_info =  kzalloc(sizeof(*drv_info), GFP_KERNEL);

> +	if (!drv_info)

> +		return -ENOMEM;


When this driver is remove all drv_info left in rpmsg_drv_list should be free'd.
We can't count on users to call rpmsg_ctrl_unregister_ctl().

> +

> +	drv_info->ctrl = ctrl;


This has the potential of creating problems - we don't know then the memory
assocaited with @ctrl will disappear on us.

> +

> +	list_add_tail(&drv_info->node, &rpmsg_drv_list);

> +

> +	return 0;

> +}

> +EXPORT_SYMBOL(rpmsg_ctrl_register_ctl);

> +

> +/**

> + * rpmsg_ctrl_unregister_ctl() -unregister control for the associated service

> + * @ctrl: the rpmsg control information

> + *

> + * This function is called by the rpmsg driver to unregister the associated

> + * service.

> + */

> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +	struct rpmsg_ctl_info *drv_info, *tmp;

> +

> +	list_for_each_entry_safe(drv_info, tmp, &rpmsg_drv_list, node) {

> +		if (drv_info->ctrl == ctrl) {

> +			list_del(&drv_info->node);

> +			kfree(drv_info);

> +		}

> +	}

> +}

> +EXPORT_SYMBOL(rpmsg_ctrl_unregister_ctl);

> +

>  static int rpmsg_ctrl_init(void)

>  {

>  	int ret;

> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h

> index a5db828b2420..5d64704c2346 100644

> --- a/include/linux/rpmsg.h

> +++ b/include/linux/rpmsg.h

> @@ -26,6 +26,19 @@ struct rpmsg_endpoint;

>  struct rpmsg_device_ops;

>  struct rpmsg_endpoint_ops;

>  

> +/**

> + * struct rpmsg_drv_ctrl_info - rpmsg ctrl structure

> + * @drv_name:	name of the associated driver

> + * @service:	the associated rpmsg service listed in @rpmsg_services

> + *

> + * This structure is used by rpmsg_ctl to link the endpoint creation to the

> + * service rpmsg driver.

> + */

> +struct rpmsg_drv_ctrl_info {

> +	const char *drv_name;

> +	u32  service;

> +};

> +

>  /**

>   * struct rpmsg_channel_info - channel info representation

>   * @name: name of service

> @@ -315,4 +328,22 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,

>  	module_driver(__rpmsg_driver, register_rpmsg_driver, \

>  			unregister_rpmsg_driver)

>  

> +#if IS_ENABLED(CONFIG_RPMSG_CTRL)

> +

> +int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

> +void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl);

> +

> +#else

> +

> +static inline int rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +	return 0;

> +}

> +

> +static inline void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)

> +{

> +}

> +

> +#endif /* IS_ENABLED(CONFIG_RPMSG_CTRL) */


Shouldn't this be in its own header, something like rpmsg_ctrl.h?

> +

>  #endif /* _LINUX_RPMSG_H */

> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h

> index e14c6dab4223..0b0cb028e0b3 100644

> --- a/include/uapi/linux/rpmsg.h

> +++ b/include/uapi/linux/rpmsg.h

> @@ -9,6 +9,20 @@

>  #include <linux/ioctl.h>

>  #include <linux/types.h>

>  

> +/**

> + * enum rpmsg_services - list of supported RPMsg services

> + *

> + * @RPMSG_RAW_SERVICE: char device RPMSG service

> + * @RPMSG_START_PRIVATE_SERVICES: private services have to be declared after.

> + */

> +enum rpmsg_services {

> +	/* Reserved services */

> +	RPMSG_RAW_SERVICE =  0,

> +

> +	/* Private services */

> +	RPMSG_START_PRIVATE_SERVICES =  1024,


We have plenty of bits in an enum type - I would set this to 4096 just to be on
the safe side.

> +};

> +

>  /**

>   * struct rpmsg_endpoint_info - endpoint info representation

>   * @name: name of service

> -- 

> 2.17.1

>
diff mbox series

Patch

diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c
index 425c3e32ada4..065e2e304019 100644
--- a/drivers/rpmsg/rpmsg_ctrl.c
+++ b/drivers/rpmsg/rpmsg_ctrl.c
@@ -27,6 +27,20 @@  struct rpmsg_ctrl_dev {
 	struct device dev;
 };
 
+/**
+ * struct rpmsg_ctl_info - control info list node
+ * @ctrl:	control driver info
+ * @node:	list node
+ *
+ * This structure is used by rpmsg_ctl to list the registered drivers services
+ */
+struct rpmsg_ctl_info {
+	const struct rpmsg_drv_ctrl_info *ctrl;
+	struct list_head node;
+};
+
+static LIST_HEAD(rpmsg_drv_list);
+
 static DEFINE_IDA(rpmsg_ctrl_ida);
 static DEFINE_IDA(rpmsg_minor_ida);
 
@@ -175,6 +189,49 @@  static struct rpmsg_driver rpmsg_ctrl_driver = {
 	.remove = rpmsg_ctrl_remove,
 };
 
+/**
+ * rpmsg_ctrl_register_ctl() -register control for the associated service
+ * @ctrl: rpmsg driver information
+ *
+ * This function is called by the rpmsg driver to register a service that will
+ * be exposed to be instantiate by the application.
+ */
+int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+	struct rpmsg_ctl_info *drv_info;
+
+	drv_info =  kzalloc(sizeof(*drv_info), GFP_KERNEL);
+	if (!drv_info)
+		return -ENOMEM;
+
+	drv_info->ctrl = ctrl;
+
+	list_add_tail(&drv_info->node, &rpmsg_drv_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(rpmsg_ctrl_register_ctl);
+
+/**
+ * rpmsg_ctrl_unregister_ctl() -unregister control for the associated service
+ * @ctrl: the rpmsg control information
+ *
+ * This function is called by the rpmsg driver to unregister the associated
+ * service.
+ */
+void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+	struct rpmsg_ctl_info *drv_info, *tmp;
+
+	list_for_each_entry_safe(drv_info, tmp, &rpmsg_drv_list, node) {
+		if (drv_info->ctrl == ctrl) {
+			list_del(&drv_info->node);
+			kfree(drv_info);
+		}
+	}
+}
+EXPORT_SYMBOL(rpmsg_ctrl_unregister_ctl);
+
 static int rpmsg_ctrl_init(void)
 {
 	int ret;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a5db828b2420..5d64704c2346 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -26,6 +26,19 @@  struct rpmsg_endpoint;
 struct rpmsg_device_ops;
 struct rpmsg_endpoint_ops;
 
+/**
+ * struct rpmsg_drv_ctrl_info - rpmsg ctrl structure
+ * @drv_name:	name of the associated driver
+ * @service:	the associated rpmsg service listed in @rpmsg_services
+ *
+ * This structure is used by rpmsg_ctl to link the endpoint creation to the
+ * service rpmsg driver.
+ */
+struct rpmsg_drv_ctrl_info {
+	const char *drv_name;
+	u32  service;
+};
+
 /**
  * struct rpmsg_channel_info - channel info representation
  * @name: name of service
@@ -315,4 +328,22 @@  static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,
 	module_driver(__rpmsg_driver, register_rpmsg_driver, \
 			unregister_rpmsg_driver)
 
+#if IS_ENABLED(CONFIG_RPMSG_CTRL)
+
+int  rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl);
+void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl);
+
+#else
+
+static inline int rpmsg_ctrl_register_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+	return 0;
+}
+
+static inline void rpmsg_ctrl_unregister_ctl(const struct rpmsg_drv_ctrl_info *ctrl)
+{
+}
+
+#endif /* IS_ENABLED(CONFIG_RPMSG_CTRL) */
+
 #endif /* _LINUX_RPMSG_H */
diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
index e14c6dab4223..0b0cb028e0b3 100644
--- a/include/uapi/linux/rpmsg.h
+++ b/include/uapi/linux/rpmsg.h
@@ -9,6 +9,20 @@ 
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
+/**
+ * enum rpmsg_services - list of supported RPMsg services
+ *
+ * @RPMSG_RAW_SERVICE: char device RPMSG service
+ * @RPMSG_START_PRIVATE_SERVICES: private services have to be declared after.
+ */
+enum rpmsg_services {
+	/* Reserved services */
+	RPMSG_RAW_SERVICE =  0,
+
+	/* Private services */
+	RPMSG_START_PRIVATE_SERVICES =  1024,
+};
+
 /**
  * struct rpmsg_endpoint_info - endpoint info representation
  * @name: name of service