diff --git a/lib/include/openamp/remoteproc.h b/lib/include/openamp/remoteproc.h index f558846f9..b2fd6c043 100644 --- a/lib/include/openamp/remoteproc.h +++ b/lib/include/openamp/remoteproc.h @@ -432,6 +432,16 @@ struct remoteproc_ops { metal_phys_addr_t da, void *va, size_t size, struct remoteproc_mem *buf); + /** + * wait_tx_buffer + * + * Wait tx buffer available + * + * @rproc - pointer to remoteproc instance + * + * return none + */ + int (*wait_tx_buffer)(struct remoteproc *rproc); }; /* Remoteproc error codes */ diff --git a/lib/include/openamp/rpmsg_virtio.h b/lib/include/openamp/rpmsg_virtio.h index 12cb47fc8..5cfab2937 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ b/lib/include/openamp/rpmsg_virtio.h @@ -109,6 +109,12 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, callbacks); } +static inline int rpmsg_virtio_wait_tx_buffer(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->wait_tx_buffer ? + rvdev->vdev->func->wait_tx_buffer(rvdev->vdev) : -EAGAIN; +} + /** * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size * diff --git a/lib/include/openamp/virtio.h b/lib/include/openamp/virtio.h index 55c8ea517..34bccaaf9 100644 --- a/lib/include/openamp/virtio.h +++ b/lib/include/openamp/virtio.h @@ -137,6 +137,7 @@ struct virtio_dispatch { void *src, int length); void (*reset_device)(struct virtio_device *dev); void (*notify)(struct virtqueue *vq); + int (*wait_tx_buffer)(struct virtio_device *dev); }; int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, diff --git a/lib/remoteproc/remoteproc_virtio.c b/lib/remoteproc/remoteproc_virtio.c index ed9f33cbc..0de31ee73 100644 --- a/lib/remoteproc/remoteproc_virtio.c +++ b/lib/remoteproc/remoteproc_virtio.c @@ -30,6 +30,17 @@ static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) rpvdev->notify(rpvdev->priv, vring_info->notifyid); } +static int rproc_virtio_wait_tx_buffer(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct remoteproc *rproc; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + rproc = rpvdev->priv; + + return rproc->ops->wait_tx_buffer ? rproc->ops->wait_tx_buffer(rproc) : -EAGAIN; +} + static unsigned char rproc_virtio_get_status(struct virtio_device *vdev) { struct remoteproc_virtio *rpvdev; @@ -179,6 +190,7 @@ static const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = { .get_features = rproc_virtio_get_features, .read_config = rproc_virtio_read_config, .notify = rproc_virtio_virtqueue_notify, + .wait_tx_buffer = rproc_virtio_wait_tx_buffer, #ifndef VIRTIO_SLAVE_ONLY /* * We suppose here that the vdev is in a shared memory so that can diff --git a/lib/rpmsg/rpmsg_virtio.c b/lib/rpmsg/rpmsg_virtio.c index c7c578d62..c5f3518e0 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ b/lib/rpmsg/rpmsg_virtio.c @@ -333,6 +333,8 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, metal_mutex_release(&rdev->lock); if (rp_hdr || !tick_count) break; + if (rpmsg_virtio_wait_tx_buffer(rvdev) >= 0) + continue; metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); tick_count--; }