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. */ /** Number of endpoints. */
#define NUM_ENDPOINTS CONFIG_IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE #define NUM_ENDPOINTS CONFIG_IPC_SERVICE_NUM_ENDPOINTS_PER_INSTANCE
struct ipc_rpmsg_ept;
/** /**
* @typedef rpmsg_ept_bound_cb * @typedef rpmsg_ept_bound_cb
* @brief Define the bound callback. * @brief Define the bound callback.
@ -33,13 +35,13 @@ extern "C" {
* *
* @param ept Endpoint of the instance just bound. * @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. /** @brief Endpoint structure.
* *
* Used to define an endpoint to be encapsulated in an RPMsg instance. * Used to define an endpoint to be encapsulated in an RPMsg instance.
*/ */
struct ipc_ept { struct ipc_rpmsg_ept {
/** RPMsg endpoint. */ /** RPMsg endpoint. */
struct rpmsg_endpoint ep; struct rpmsg_endpoint ep;
@ -62,7 +64,7 @@ struct ipc_ept {
*/ */
struct ipc_rpmsg_instance { struct ipc_rpmsg_instance {
/** Endpoints in the instance. */ /** Endpoints in the instance. */
struct ipc_ept endpoint[NUM_ENDPOINTS]; struct ipc_rpmsg_ept endpoint[NUM_ENDPOINTS];
/** RPMsg virtIO device. */ /** RPMsg virtIO device. */
struct rpmsg_virtio_device rvdev; 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. * @retval Other errno codes depending on the OpenAMP implementation.
*/ */
int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role, 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> #include <ipc/ipc_service.h>
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
#define APP_TASK_STACK_SIZE 1024 #define APP_TASK_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE); 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_rx1_sem, 0, 1);
static K_SEM_DEFINE(data_rx2_sem, 0, 1); static K_SEM_DEFINE(data_rx2_sem, 0, 1);
static struct ipc_ept *ept_1; static struct ipc_ept ept_1;
static struct ipc_ept *ept_2; static struct ipc_ept ept_2;
static void ept_bound_1(void *priv) 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(arg1);
ARG_UNUSED(arg2); ARG_UNUSED(arg2);
ARG_UNUSED(arg3); ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0; int status = 0;
uint8_t message = 0U; uint8_t message = 0U;
printk("\r\nIPC Service [remote 1] demo started\r\n"); 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 = { static struct ipc_ept_cfg ept_cfg = {
.name = "ep_1", .name = "ep_1",
.prio = 0, .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) { if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status); printk("ipc_service_register_endpoint failed %d\n", status);
return; return;
@ -101,7 +107,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
printk("Remote [1] received a message: %d\n", message); printk("Remote [1] received a message: %d\n", message);
message++; message++;
status = ipc_service_send(ept_1, &message, sizeof(message)); status = ipc_service_send(&ept_1, &message, sizeof(message));
if (status < 0) { if (status < 0) {
printk("send_message(%d) failed with status %d\n", printk("send_message(%d) failed with status %d\n",
message, status); message, status);
@ -117,11 +123,15 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1); ARG_UNUSED(arg1);
ARG_UNUSED(arg2); ARG_UNUSED(arg2);
ARG_UNUSED(arg3); ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0; int status = 0;
uint8_t message = 0U; uint8_t message = 0U;
printk("\r\nIPC Service [remote 2] demo started\r\n"); 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 = { static struct ipc_ept_cfg ept_cfg = {
.name = "ep_2", .name = "ep_2",
.prio = 0, .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) { if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status); 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); printk("Remote [2] received a message: %d\n", message);
message++; message++;
status = ipc_service_send(ept_2, &message, sizeof(message)); status = ipc_service_send(&ept_2, &message, sizeof(message));
if (status < 0) { if (status < 0) {
printk("send_message(%d) failed with status %d\n", printk("send_message(%d) failed with status %d\n",
message, status); message, status);

View file

@ -15,6 +15,8 @@
#include <ipc/ipc_service.h> #include <ipc/ipc_service.h>
#define MI_BACKEND_DRIVER_NAME "MI_BACKEND"
#define APP_TASK_STACK_SIZE 1024 #define APP_TASK_STACK_SIZE 1024
K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE); 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_rx1_sem, 0, 1);
static K_SEM_DEFINE(data_rx2_sem, 0, 1); static K_SEM_DEFINE(data_rx2_sem, 0, 1);
static struct ipc_ept *ept_1; static struct ipc_ept ept_1;
static struct ipc_ept *ept_2; static struct ipc_ept ept_2;
static void ept_bound_1(void *priv) 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(arg1);
ARG_UNUSED(arg2); ARG_UNUSED(arg2);
ARG_UNUSED(arg3); ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0; int status = 0;
uint8_t message = 0U; uint8_t message = 0U;
printk("\r\nIPC Service [master 1] demo started\r\n"); 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 = { static struct ipc_ept_cfg ept_cfg = {
.name = "ep_1", .name = "ep_1",
.prio = 0, .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) { if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status); printk("ipc_service_register_endpoint failed %d\n", status);
return; return;
@ -97,7 +103,7 @@ void app_task_1(void *arg1, void *arg2, void *arg3)
k_sem_take(&bound_ept1_sem, K_FOREVER); k_sem_take(&bound_ept1_sem, K_FOREVER);
while (message < 100) { while (message < 100) {
status = ipc_service_send(ept_1, &message, sizeof(message)); status = ipc_service_send(&ept_1, &message, sizeof(message));
if (status < 0) { if (status < 0) {
printk("send_message(%d) failed with status %d\n", printk("send_message(%d) failed with status %d\n",
message, status); message, status);
@ -119,11 +125,15 @@ void app_task_2(void *arg1, void *arg2, void *arg3)
ARG_UNUSED(arg1); ARG_UNUSED(arg1);
ARG_UNUSED(arg2); ARG_UNUSED(arg2);
ARG_UNUSED(arg3); ARG_UNUSED(arg3);
const struct device *ipc_instance;
int status = 0; int status = 0;
uint8_t message = 0U; uint8_t message = 0U;
printk("\r\nIPC Service [master 2] demo started\r\n"); 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 = { static struct ipc_ept_cfg ept_cfg = {
.name = "ep_2", .name = "ep_2",
.prio = 0, .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) { if (status < 0) {
printk("ipc_service_register_endpoint failed %d\n", status); 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); k_sem_take(&bound_ept2_sem, K_FOREVER);
while (message < 100) { while (message < 100) {
status = ipc_service_send(ept_2, &message, sizeof(message)); status = ipc_service_send(&ept_2, &message, sizeof(message));
if (status < 0) { if (status < 0) {
printk("send_message(%d) failed with status %d\n", printk("send_message(%d) failed with status %d\n",
message, status); 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 rpmsg_virtio_device *p_rvdev;
struct ipc_rpmsg_instance *instance; struct ipc_rpmsg_instance *instance;
struct ipc_ept *ept; struct ipc_rpmsg_ept *ept;
int err; int err;
p_rvdev = CONTAINER_OF(rdev, struct rpmsg_virtio_device, rdev); 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, 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; struct rpmsg_device *rdev;

View file

@ -17,6 +17,8 @@
#include "ipc_rpmsg_static_vrings_mi.h" #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); 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 #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 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) 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; 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++) { for (size_t i = 0; i < NUM_ENDPOINTS; i++) {
if (rpmsg_instance->endpoint[i].name == NULL) { 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; 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 */ /* Notify the remote site that binding has occurred */
rpmsg_send(&ept->ep, (uint8_t *)"", 0); 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) 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 (len == 0) {
if (!ept->bound) { if (!ept->bound) {
@ -239,14 +246,18 @@ static int init_instance(struct rpmsg_mi_instance *instance)
return 0; 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 ipc_rpmsg_instance *rpmsg_instance;
struct rpmsg_mi_instance *instance; struct rpmsg_mi_instance *instance;
struct ipc_ept *ept; struct ipc_rpmsg_ept *rpmsg_ept;
int err; int err;
if (!cfg || !r_ept) { ARG_UNUSED(dev);
if (!cfg || !token) {
return -EINVAL; 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; instance->is_initialized = true;
} }
ept = get_available_ept_slot(rpmsg_instance); rpmsg_ept = get_available_ept_slot(rpmsg_instance);
if (ept == NULL) { if (rpmsg_ept == NULL) {
return -ENODEV; return -ENODEV;
} }
ept->name = cfg->name; rpmsg_ept->name = cfg->name;
ept->cb = &cfg->cb; rpmsg_ept->cb = &cfg->cb;
ept->priv = cfg->priv; rpmsg_ept->priv = cfg->priv;
ept->bound = false; rpmsg_ept->bound = false;
ept->ep.priv = ept; 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) { if (err != 0) {
return err; return err;
} }
*r_ept = ept; (*token) = rpmsg_ept;
return 0; return 0;
} }
const static struct ipc_service_backend backend = { const static struct ipc_service_backend backend_ops = {
.name = "RPMSG backend - static VRINGs (multi-instance)",
.send = send, .send = send,
.register_endpoint = register_ept, .register_endpoint = register_ept,
}; };
@ -321,6 +331,9 @@ static int backend_init(const struct device *dev)
VIRTIO_DEV_MASTER : VIRTIO_DEV_SLAVE; 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);