/* * Copyright (c) 2021 Carlo Caione * * SPDX-License-Identifier: Apache-2.0 */ #include #include static void rpmsg_service_unbind(struct rpmsg_endpoint *ep) { rpmsg_destroy_ept(ep); } static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) { struct rpmsg_virtio_device *p_rvdev; struct ipc_rpmsg_instance *instance; struct ipc_rpmsg_ept *ept; int err; p_rvdev = CONTAINER_OF(rdev, struct rpmsg_virtio_device, rdev); instance = CONTAINER_OF(p_rvdev->shpool, struct ipc_rpmsg_instance, shm_pool); for (size_t i = 0; i < NUM_ENDPOINTS; i++) { ept = &instance->endpoint[i]; if (strcmp(name, ept->name) == 0) { /* * The destination address is 'dest' so ns_bind_cb() is * *NOT* called on the REMOTE side. The bound_cb() * function will eventually take care of notifying the * REMOTE side if needed. */ err = rpmsg_create_ept(&ept->ep, rdev, name, RPMSG_ADDR_ANY, dest, instance->cb, rpmsg_service_unbind); if (err != 0) { return; } ept->bound = true; if (instance->bound_cb) { instance->bound_cb(ept); } } } } int ipc_rpmsg_register_ept(struct ipc_rpmsg_instance *instance, unsigned int role, struct ipc_rpmsg_ept *ept) { struct rpmsg_device *rdev; if (!instance || !ept) { return -EINVAL; } rdev = rpmsg_virtio_get_rpmsg_device(&instance->rvdev); if (role == RPMSG_REMOTE) { /* * The destination address is RPMSG_ADDR_ANY, this will trigger * the ns_bind_cb() callback function on the HOST side. */ return rpmsg_create_ept(&ept->ep, rdev, ept->name, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, instance->cb, rpmsg_service_unbind); } return RPMSG_SUCCESS; } int ipc_rpmsg_init(struct ipc_rpmsg_instance *instance, unsigned int role, unsigned int buffer_size, struct metal_io_region *shm_io, struct virtio_device *vdev, void *shb, size_t size, rpmsg_ns_bind_cb p_bind_cb) { rpmsg_ns_bind_cb bind_cb = p_bind_cb; if (!instance || !shb) { return -EINVAL; } if (p_bind_cb == NULL) { bind_cb = ns_bind_cb; } if (role == RPMSG_HOST) { struct rpmsg_virtio_config config = { 0 }; config.h2r_buf_size = (uint32_t) buffer_size; config.r2h_buf_size = (uint32_t) buffer_size; rpmsg_virtio_init_shm_pool(&instance->shm_pool, shb, size); return rpmsg_init_vdev_with_config(&instance->rvdev, vdev, bind_cb, shm_io, &instance->shm_pool, &config); } else { return rpmsg_init_vdev(&instance->rvdev, vdev, bind_cb, shm_io, NULL); } } int ipc_rpmsg_deinit(struct ipc_rpmsg_instance *instance, unsigned int role) { if (!instance) { return -EINVAL; } rpmsg_deinit_vdev(&instance->rvdev); if (role == RPMSG_HOST) { memset(&instance->shm_pool, 0, sizeof(struct rpmsg_virtio_shm_pool)); } return 0; }