ipc_service: mi: Convert to device driver

As part of the work to support multiple IPC instances / backends using
IPC service, the static vrings mi code must be reworked to resemble a
classic device driver.

Fix also the sample using it.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
Carlo Caione 2021-10-25 17:40:43 +02:00 committed by Carles Cufí
commit 2c08114c27
5 changed files with 75 additions and 40 deletions

View file

@ -24,6 +24,8 @@ extern "C" {
/** Number of endpoints. */
#define NUM_ENDPOINTS CONFIG_IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE
struct ipc_rpmsg_ept;
/**
* @typedef rpmsg_ept_bound_cb
* @brief Define the bound callback.
@ -33,13 +35,13 @@ extern "C" {
*
* @param ept Endpoint of the instance just bound.
*/
typedef void (*rpmsg_ept_bound_cb)(struct ipc_ept *ept);
typedef void (*rpmsg_ept_bound_cb)(struct ipc_rpmsg_ept *ept);
/** @brief Endpoint structure.
*
* Used to define an endpoint to be encapsulated in an RPMsg instance.
*/
struct ipc_ept {
struct ipc_rpmsg_ept {
/** RPMsg endpoint. */
struct rpmsg_endpoint ep;
@ -62,7 +64,7 @@ struct ipc_ept {
*/
struct ipc_rpmsg_instance {
/** Endpoints in the instance. */
struct ipc_ept endpoint[NUM_ENDPOINTS];
struct ipc_rpmsg_ept endpoint[NUM_ENDPOINTS];
/** RPMsg virtIO device. */
struct rpmsg_virtio_device rvdev;
@ -115,7 +117,7 @@ int ipc_rpmsg_init(struct ipc_rpmsg_instance *instance,
* @retval Other errno codes depending on the OpenAMP implementation.
*/
int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role,
struct ipc_ept *ept);
struct ipc_rpmsg_ept *ept);
/**
* @}

View file

@ -14,6 +14,8 @@
#include <ipc/ipc_service.h>
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
#define APP_TASK_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE);
@ -31,8 +33,8 @@ static K_SEM_DEFINE(bound_ept2_sem, 0, 1);
static K_SEM_DEFINE(data_rx1_sem, 0, 1);
static K_SEM_DEFINE(data_rx2_sem, 0, 1);
static struct ipc_ept *ept_1;
static struct ipc_ept *ept_2;
static struct ipc_ept ept_1;
static struct ipc_ept ept_2;
static void ept_bound_1(void *priv)
{
@ -71,11 +73,15 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0;
uint8_t message = 0U;
printk("\r\nIPC Service [remote 1] demo started\r\n");
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
static struct ipc_ept_cfg ept_cfg = {
.name = "ep_1",
.prio = 0,
@ -87,7 +93,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
},
};
status = ipc_service_register_endpoint(&ept_1, &ept_cfg);
status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status);
return;
@ -101,7 +107,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
printk("Remote [1] received a message: %d\n", message);
message++;
status = ipc_service_send(ept_1, &message, sizeof(message));
status = ipc_service_send(&ept_1, &message, sizeof(message));
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
@ -117,11 +123,15 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0;
uint8_t message = 0U;
printk("\r\nIPC Service [remote 2] demo started\r\n");
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
static struct ipc_ept_cfg ept_cfg = {
.name = "ep_2",
.prio = 0,
@ -133,7 +143,7 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
},
};
status = ipc_service_register_endpoint(&ept_2, &ept_cfg);
status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status);
@ -148,7 +158,7 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
printk("Remote [2] received a message: %d\n", message);
message++;
status = ipc_service_send(ept_2, &message, sizeof(message));
status = ipc_service_send(&ept_2, &message, sizeof(message));
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);

View file

@ -15,6 +15,8 @@
#include <ipc/ipc_service.h>
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
#define APP_TASK_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE);
@ -32,8 +34,8 @@ static K_SEM_DEFINE(bound_ept2_sem, 0, 1);
static K_SEM_DEFINE(data_rx1_sem, 0, 1);
static K_SEM_DEFINE(data_rx2_sem, 0, 1);
static struct ipc_ept *ept_1;
static struct ipc_ept *ept_2;
static struct ipc_ept ept_1;
static struct ipc_ept ept_2;
static void ept_bound_1(void *priv)
{
@ -72,11 +74,15 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0;
uint8_t message = 0U;
printk("\r\nIPC Service [master 1] demo started\r\n");
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
static struct ipc_ept_cfg ept_cfg = {
.name = "ep_1",
.prio = 0,
@ -88,7 +94,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
},
};
status = ipc_service_register_endpoint(&ept_1, &ept_cfg);
status = ipc_service_register_endpoint(ipc_instance, &ept_1, &ept_cfg);
if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status);
return;
@ -97,7 +103,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
k_sem_take(&bound_ept1_sem, K_FOREVER);
while (message < 100) {
status = ipc_service_send(ept_1, &message, sizeof(message));
status = ipc_service_send(&ept_1, &message, sizeof(message));
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);
@ -119,11 +125,15 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0;
uint8_t message = 0U;
printk("\r\nIPC Service [master 2] demo started\r\n");
ipc_instance = device_get_binding(MI_BACKEND_DRIVER_NAME);
static struct ipc_ept_cfg ept_cfg = {
.name = "ep_2",
.prio = 0,
@ -135,7 +145,7 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
},
};
status = ipc_service_register_endpoint(&ept_2, &ept_cfg);
status = ipc_service_register_endpoint(ipc_instance, &ept_2, &ept_cfg);
if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status);
@ -145,7 +155,7 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
k_sem_take(&bound_ept2_sem, K_FOREVER);
while (message < 100) {
status = ipc_service_send(ept_2, &message, sizeof(message));
status = ipc_service_send(&ept_2, &message, sizeof(message));
if (status < 0) {
printk("send_message(%d) failed with status %d\n",
message, status);

View file

@ -16,7 +16,7 @@ static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t des
{
struct rpmsg_virtio_device *p_rvdev;
struct ipc_rpmsg_instance *instance;
struct ipc_ept *ept;
struct ipc_rpmsg_ept *ept;
int err;
p_rvdev = CONTAINER_OF(rdev, struct rpmsg_virtio_device, rdev);
@ -41,7 +41,7 @@ static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t des
}
int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role,
struct ipc_ept *ept)
struct ipc_rpmsg_ept *ept)
{
struct rpmsg_device *rdev;

View file

@ -17,6 +17,8 @@
#include "ipc_rpmsg_static_vrings_mi.h"
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
LOG_MODULE_REGISTER(ipc_rpmsg_multi_instance, CONFIG_IPC_SERVICE_LOG_LEVEL);
#define WQ_STACK_SIZE CONFIG_IPC_SERVICE_BACKEND_RPMSG_MI_WQ_STACK_SIZE
@ -74,9 +76,14 @@ struct {
static struct rpmsg_mi_instance instance[NUM_INSTANCES];
static int send(struct ipc_ept *ept, const void *data, size_t len)
static int send(const struct device *instance, void *token,
const void *data, size_t len)
{
return rpmsg_send(&ept->ep, data, len);
struct ipc_rpmsg_ept *rpmsg_ept;
rpmsg_ept = (struct ipc_rpmsg_ept *) token;
return rpmsg_send(&rpmsg_ept->ep, data, len);
}
static struct rpmsg_mi_instance *get_available_instance(const struct ipc_ept_cfg *cfg)
@ -90,7 +97,7 @@ static struct rpmsg_mi_instance *get_available_instance(const struct ipc_ept_cfg
return NULL;
}
static struct ipc_ept *get_available_ept_slot(struct ipc_rpmsg_instance *rpmsg_instance)
static struct ipc_rpmsg_ept *get_available_ept_slot(struct ipc_rpmsg_instance *rpmsg_instance)
{
for (size_t i = 0; i < NUM_ENDPOINTS; i++) {
if (rpmsg_instance->endpoint[i].name == NULL) {
@ -168,7 +175,7 @@ static void shm_configure(struct rpmsg_mi_instance *instance)
instance->vr.shm_size = shm_local_size;
}
static void bound_cb(struct ipc_ept *ept)
static void bound_cb(struct ipc_rpmsg_ept *ept)
{
/* Notify the remote site that binding has occurred */
rpmsg_send(&ept->ep, (uint8_t *)"", 0);
@ -180,9 +187,9 @@ static void bound_cb(struct ipc_ept *ept)
static int ept_cb(struct rpmsg_endpoint *ep, void *data, size_t len, uint32_t src, void *priv)
{
struct ipc_ept *ept;
struct ipc_rpmsg_ept *ept;
ept = (struct ipc_ept *) priv;
ept = (struct ipc_rpmsg_ept *) priv;
if (len == 0) {
if (!ept->bound) {
@ -239,14 +246,18 @@ static int init_instance(struct rpmsg_mi_instance *instance)
return 0;
}
static int register_ept(struct ipc_ept **r_ept, const struct ipc_ept_cfg *cfg)
static int register_ept(const struct device *dev,
void **token,
const struct ipc_ept_cfg *cfg)
{
struct ipc_rpmsg_instance *rpmsg_instance;
struct rpmsg_mi_instance *instance;
struct ipc_ept *ept;
struct ipc_rpmsg_ept *rpmsg_ept;
int err;
if (!cfg || !r_ept) {
ARG_UNUSED(dev);
if (!cfg || !token) {
return -EINVAL;
}
@ -283,29 +294,28 @@ static int register_ept(struct ipc_ept **r_ept, const struct ipc_ept_cfg *cfg)
instance->is_initialized = true;
}
ept = get_available_ept_slot(rpmsg_instance);
if (ept == NULL) {
rpmsg_ept = get_available_ept_slot(rpmsg_instance);
if (rpmsg_ept == NULL) {
return -ENODEV;
}
ept->name = cfg->name;
ept->cb = &cfg->cb;
ept->priv = cfg->priv;
ept->bound = false;
ept->ep.priv = ept;
rpmsg_ept->name = cfg->name;
rpmsg_ept->cb = &cfg->cb;
rpmsg_ept->priv = cfg->priv;
rpmsg_ept->bound = false;
rpmsg_ept->ep.priv = rpmsg_ept;
err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, ept);
err = ipc_rpmsg_register_ept(rpmsg_instance, instance->role, rpmsg_ept);
if (err != 0) {
return err;
}
*r_ept = ept;
(*token) = rpmsg_ept;
return 0;
}
const static struct ipc_service_backend backend = {
.name = "RPMSG backend - static VRINGs (multi-instance)",
const static struct ipc_service_backend backend_ops = {
.send = send,
.register_endpoint = register_ept,
};
@ -321,6 +331,9 @@ static int backend_init(const struct device *dev)
VIRTIO_DEV_MASTER : VIRTIO_DEV_SLAVE;
}
return ipc_service_register_backend(&backend);
return 0;
}
SYS_INIT(backend_init, POST_KERNEL, CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY);
DEVICE_DEFINE(mi_backend, MI_BACKEND_DRIVER_NAME, &backend_init, NULL, NULL,
NULL, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&backend_ops);