blob: 0ef0c9ca950013cb258b0e77f8871e17ccf4f4ba [file] [log] [blame]
/*
* Copyright (c) 2021 Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <openamp/virtio_ring.h>
#include <openamp/rpmsg_virtio.h>
#include <zephyr/ipc/ipc_static_vrings.h>
/*
* Endpoint registration flow:
*
* >>> Case #1: Endpoint registered on HOST first <<<
*
* [B] backend
* [O] OpenAMP
*
* REMOTE HOST
* -----------------------------------------------------------------
* [B] register_ept **
* [B] register_ept **
* [B] ipc_rpmsg_register_ept
* [B] rpmsg_create_ept
* [O] rpmsg_send_ns_message
* [O] virtqueue_kick
* [O] virtio_notify_cb
* [B] mbox_send
* [B] mbox_callback
* [B] mbox_callback_process
* [B] virtqueue_notification
* [O] rpmsg_virtio_rx_callback
* [B] ns_bind_cb
* [B] rpmsg_create_ept
* [B] bound_cb
* [B] rpmsg_send
* [B] virtio_notify_cb
* [B] mbox_send
* [B] mbox_callback
* [B] mbox_callback_process
* [B] virtqueue_notification
* [O] rpmsg_virtio_rx_callback
* [O] ept_cb
* [B] bound_cb
*
* >>> Case #2: Endpoint registered on REMOTE first <<<
*
* [B] backend
* [O] OpenAMP
*
* REMOTE HOST
* -----------------------------------------------------------------
* [B] register_ept **
* [B] ipc_rpmsg_register_ept
* [B] rpmsg_create_ept
* [O] rpmsg_send_ns_message
* [O] virtqueue_kick
* [O] virtio_notify_cb
* [O] mbox_send
* [B] mbox_callback
* [B] mbox_callback_process
* [B] virtqueue_notification
* [O] rpmsg_virtio_rx_callback
* [B] ns_bind_cb
*
* [B] register_ept **
* [B] rpmsg_create_ept
* [B] bound_cb
* [B] rpmsg_send
* [B] virtio_notify_cb
* [B] mbox_send
* [B] mbox_callback
* [B] mbox_callback_process
* [B] virtqueue_notification
* [O] rpmsg_virtio_rx_callback
* [O] ept_cb
* [B] bound_cb
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Endpoint registration flow (with focus on backend):
*
* >>> Case #1: Endpoint registered on HOST first <<<
*
* REMOTE HOST
* -----------------------------------------------------------------
* register_ept()
* register_ept_on_host()
* get_ept() returns NULL
* name is cached in rpmsg_ept->name
* register_ept()
* register_ept_on_remote()
* ipc_rpmsg_register_ept()
* ns_bind_cb()
* get_ept() returns endpoint with cached name
* advertise_ept()
* rpmsg_create_ept()
* bound_cb()
* rpmsg_send()
* mbox_callback()
* mbox_callback_process()
* virtqueue_notification()
* ept_cb()
* bound_cb()
*
* >>> Case #2: Endpoint registered on REMOTE first <<<
*
* REMOTE HOST
* -----------------------------------------------------------------
* register_ept()
* register_ept_on_remote()
* ipc_rpmsg_register_ept()
* ns_bind_cb()
* get_ept() return NULL
* name is cached in rpmsg_ept->name
* ...
* register_ept()
* register_ept_on_host()
* get_ept() returns endpoint with cached name
* advertise_ept()
* rpmsg_create_ept()
* bound_cb()
* rpmsg-send()
* mbox_callback()
* mbox_callback_process()
* virtqueue_notification()
* ept_cb()
* bound_cb()
*
*/
#define VDEV_STATUS_SIZE (4) /* Size of status region */
#define VIRTQUEUE_ID_HOST (0)
#define VIRTQUEUE_ID_REMOTE (1)
#define ROLE_HOST VIRTIO_DEV_DRIVER
#define ROLE_REMOTE VIRTIO_DEV_DEVICE
static inline size_t vq_ring_size(unsigned int num, unsigned int buf_size)
{
return (buf_size * num);
}
static inline size_t shm_size(unsigned int num, unsigned int buf_size)
{
return (VDEV_STATUS_SIZE + (VRING_COUNT * vq_ring_size(num, buf_size)) +
(VRING_COUNT * vring_size(num, VRING_ALIGNMENT)));
}
static inline unsigned int optimal_num_desc(size_t shm_size, unsigned int buf_size)
{
size_t available, single_alloc;
unsigned int num_desc;
available = shm_size - VDEV_STATUS_SIZE;
single_alloc = VRING_COUNT * (vq_ring_size(1, buf_size) + vring_size(1, VRING_ALIGNMENT));
num_desc = (unsigned int) (available / single_alloc);
return (1 << (find_msb_set(num_desc) - 1));
}