Skip to content

Commit

Permalink
remoteproc_virtio: optimize the remoteproc virtio transport layer
Browse files Browse the repository at this point in the history
1. Implement the rproc_virtio_create_virtqueues() and
   rproc_virtio_delete_virtqueues().
2. Because 1, also modified the rpmsg init.

Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
  • Loading branch information
CV-Bowen committed Oct 16, 2023
1 parent 329fe10 commit f7e1a49
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 46 deletions.
6 changes: 6 additions & 0 deletions lib/include/openamp/rpmsg_virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
callbacks, NULL);
}

static inline void
rpmsg_virtio_delete_virtqueues(struct rpmsg_virtio_device *rvdev)
{
virtio_delete_virtqueues(rvdev->vdev);
}

/**
* @brief Get rpmsg virtio buffer size
*
Expand Down
135 changes: 95 additions & 40 deletions lib/remoteproc/remoteproc_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,92 @@
#include <metal/utilities.h>
#include <metal/alloc.h>

static void rproc_virtio_delete_virtqueues(struct virtio_device *vdev)
{
struct virtio_vring_info *vring_info;
unsigned int i;

if (vdev->vrings_info) {
for (i = 0; i < vdev->vrings_num; i++) {
vring_info = &vdev->vrings_info[i];
if (vring_info->vq) {
virtqueue_free(vring_info->vq);
}
}
}
}

static int rproc_virtio_create_virtqueue(struct virtio_device *vdev,
unsigned int flags,
unsigned int idx,
const char *name,
vq_callback callback)
{
struct virtio_vring_info *vring_info;
struct vring_alloc_info *vring_alloc;
int ret;
(void)flags;

/* Get the vring information */
vring_info = &vdev->vrings_info[idx];
vring_alloc = &vring_info->info;

/* Alloc the virtqueue and init it */
metal_assert(!vring_info->vq);
vring_info->vq = virtqueue_allocate(vring_alloc->num_descs);
if (!vring_info->vq) {
return ERROR_NO_MEM;
}

#ifndef VIRTIO_DEVICE_ONLY
if (vdev->role == VIRTIO_DEV_DRIVER) {
size_t offset = metal_io_virt_to_offset(vring_info->io,
vring_alloc->vaddr);
size_t size = vring_size(vring_alloc->num_descs,
vring_alloc->align);
metal_io_block_set(vring_info->io, offset, 0, size);
}
#endif
ret = virtqueue_create(vdev, idx, name, vring_alloc, callback,
vdev->func->notify, vring_info->vq);
if (ret) {
return ret;
}
return 0;
}

static int rproc_virtio_create_virtqueues(struct virtio_device *vdev,
unsigned int flags,
unsigned int nvqs,
const char *names[],
vq_callback callbacks[],
void *callback_args[])
{
unsigned int i;
int ret;
(void)callback_args;

/* Check vrings number */
if (nvqs > vdev->vrings_num)
return ERROR_VQUEUE_INVLD_PARAM;

metal_assert(vdev->vrings_info);

/* set the notification id for vrings */
for (i = 0; i < nvqs; i++) {
ret = rproc_virtio_create_virtqueue(vdev, flags, i, names[i],
callbacks[i]);
if (ret) {
goto err;
}
}
return 0;

err:
rproc_virtio_delete_virtqueues(vdev);
return ret;
}

static void rproc_virtio_virtqueue_notify(struct virtqueue *vq)
{
struct remoteproc_virtio *rpvdev;
Expand Down Expand Up @@ -183,6 +269,8 @@ static void rproc_virtio_reset_device(struct virtio_device *vdev)
#endif

static const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = {
.create_virtqueues = rproc_virtio_create_virtqueues,
.delete_virtqueues = rproc_virtio_delete_virtqueues,
.get_status = rproc_virtio_get_status,
.get_features = rproc_virtio_get_features,
.read_config = rproc_virtio_read_config,
Expand Down Expand Up @@ -213,46 +301,28 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid,
struct fw_rsc_vdev *vdev_rsc = rsc;
struct virtio_device *vdev;
unsigned int num_vrings = vdev_rsc->num_of_vrings;
unsigned int i;

rpvdev = metal_allocate_memory(sizeof(*rpvdev));
if (!rpvdev)
return NULL;
vrings_info = metal_allocate_memory(sizeof(*vrings_info) * num_vrings);
if (!vrings_info)
goto err0;
goto err;
memset(rpvdev, 0, sizeof(*rpvdev));
memset(vrings_info, 0, sizeof(*vrings_info));
vdev = &rpvdev->vdev;

for (i = 0; i < num_vrings; i++) {
struct virtqueue *vq;
#ifndef VIRTIO_DEVICE_ONLY
struct fw_rsc_vdev_vring *vring_rsc;
#endif
unsigned int num_extra_desc = 0;

#ifndef VIRTIO_DEVICE_ONLY
vring_rsc = &vdev_rsc->vring[i];
if (role == VIRTIO_DEV_DRIVER) {
num_extra_desc = vring_rsc->num;
}
#endif
vq = virtqueue_allocate(num_extra_desc);
if (!vq)
goto err1;
vrings_info[i].vq = vq;
}

/* Initialize the remoteproc virtio */
rpvdev->notify = notify;
rpvdev->priv = priv;
vdev->vrings_info = vrings_info;
/* Assuming the shared memory has been mapped and registered if
* necessary
*/
rpvdev->vdev_rsc = vdev_rsc;
rpvdev->vdev_rsc_io = rsc_io;

/* Initialize the virtio device */
vdev = &rpvdev->vdev;
vdev->vrings_info = vrings_info;
vdev->notifyid = notifyid;
vdev->role = role;
vdev->reset_cb = rst_cb;
Expand All @@ -268,33 +338,18 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid,
#endif

return &rpvdev->vdev;

err1:
for (i = 0; i < num_vrings; i++) {
if (vrings_info[i].vq)
metal_free_memory(vrings_info[i].vq);
}
metal_free_memory(vrings_info);
err0:
err:
metal_free_memory(rpvdev);
return NULL;
return &rpvdev->vdev;
}

void rproc_virtio_remove_vdev(struct virtio_device *vdev)
{
struct remoteproc_virtio *rpvdev;
unsigned int i;

if (!vdev)
return;
rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev);
for (i = 0; i < vdev->vrings_num; i++) {
struct virtqueue *vq;

vq = vdev->vrings_info[i].vq;
if (vq)
metal_free_memory(vq);
}
if (vdev->vrings_info)
metal_free_memory(vdev->vrings_info);
metal_free_memory(rpvdev);
Expand Down
31 changes: 25 additions & 6 deletions lib/rpmsg/rpmsg_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,8 +757,6 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
vq_names[1] = "tx_vq";
callback[0] = rpmsg_virtio_rx_callback;
callback[1] = rpmsg_virtio_tx_callback;
rvdev->rvq = vdev->vrings_info[0].vq;
rvdev->svq = vdev->vrings_info[1].vq;
}
#endif /*!VIRTIO_DEVICE_ONLY*/

Expand All @@ -769,8 +767,6 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
vq_names[1] = "rx_vq";
callback[0] = rpmsg_virtio_tx_callback;
callback[1] = rpmsg_virtio_rx_callback;
rvdev->rvq = vdev->vrings_info[1].vq;
rvdev->svq = vdev->vrings_info[0].vq;
}
#endif /*!VIRTIO_DRIVER_ONLY*/
rvdev->shbuf_io = shm_io;
Expand All @@ -782,6 +778,21 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
if (status != RPMSG_SUCCESS)
return status;

/* Create virtqueue success, assign back the virtqueue */
#ifndef VIRTIO_DEVICE_ONLY
if (role == RPMSG_HOST) {
rvdev->rvq = vdev->vrings_info[0].vq;
rvdev->svq = vdev->vrings_info[1].vq;
}
#endif /*!VIRTIO_DEVICE_ONLY*/

#ifndef VIRTIO_DRIVER_ONLY
if (role == RPMSG_REMOTE) {
rvdev->rvq = vdev->vrings_info[1].vq;
rvdev->svq = vdev->vrings_info[0].vq;
}
#endif /*!VIRTIO_DRIVER_ONLY*/

/*
* Suppress "tx-complete" interrupts
* since send method use busy loop when buffer pool exhaust
Expand Down Expand Up @@ -809,7 +820,8 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
rvdev->config.r2h_buf_size);

if (!buffer) {
return RPMSG_ERR_NO_BUFF;
status = RPMSG_ERR_NO_BUFF;
goto err;
}

vqbuf.buf = buffer;
Expand All @@ -823,7 +835,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
buffer);

if (status != RPMSG_SUCCESS) {
return status;
goto err;
}
}
}
Expand All @@ -848,6 +860,12 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
#endif /*!VIRTIO_DEVICE_ONLY*/

return status;

#ifndef VIRTIO_DEVICE_ONLY
err:
rpmsg_virtio_delete_virtqueues(rvdev);
return status;
#endif /*!VIRTIO_DEVICE_ONLY*/
}

void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)
Expand All @@ -867,6 +885,7 @@ void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev)
rvdev->rvq = 0;
rvdev->svq = 0;

rpmsg_virtio_delete_virtqueues(rvdev);
metal_mutex_deinit(&rdev->lock);
}
}

0 comments on commit f7e1a49

Please sign in to comment.