From 05f138ea8aaf007f97c24b6208d94fe8265d9ea5 Mon Sep 17 00:00:00 2001 From: Guiding Li Date: Thu, 18 Nov 2021 20:54:45 +0800 Subject: [PATCH] openamp: add new ops wait_notified() support This can avoid looping check tx buffer Signed-off-by: Guiding Li --- lib/include/openamp/remoteproc.h | 12 ++++++++++++ lib/include/openamp/remoteproc_virtio.h | 3 +++ lib/include/openamp/rpmsg.h | 1 + lib/include/openamp/rpmsg_virtio.h | 9 +++++++++ lib/include/openamp/virtio.h | 1 + lib/remoteproc/remoteproc.c | 11 +++++++++++ lib/remoteproc/remoteproc_virtio.c | 16 ++++++++++++++++ lib/rpmsg/rpmsg_virtio.c | 7 +++++++ 8 files changed, 60 insertions(+) diff --git a/lib/include/openamp/remoteproc.h b/lib/include/openamp/remoteproc.h index b19b2e501..6dd05ac14 100644 --- a/lib/include/openamp/remoteproc.h +++ b/lib/include/openamp/remoteproc.h @@ -433,6 +433,18 @@ struct remoteproc_ops { metal_phys_addr_t da, void *va, size_t size, struct remoteproc_mem *buf); + /** + * wait_notified + * + * Wait for remote notified, when there is no TX buffer anymore. + * Set to NULL means use usleep to TX buffer available. + * + * @rproc - pointer to remoteproc instance + * @id - the notifyid + * + * return 0 means there is notify available, otherwise negative value. + */ + int (*wait_notified)(struct remoteproc *rproc, uint32_t id); }; /* Remoteproc error codes */ diff --git a/lib/include/openamp/remoteproc_virtio.h b/lib/include/openamp/remoteproc_virtio.h index 70cff9771..0020d1660 100644 --- a/lib/include/openamp/remoteproc_virtio.h +++ b/lib/include/openamp/remoteproc_virtio.h @@ -22,6 +22,7 @@ extern "C" { /* define vdev notification function user should implement */ typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); +typedef int (*rpvdev_wait_notified_func)(void *priv, uint32_t id); /** * struct remoteproc_virtio @@ -37,6 +38,7 @@ struct remoteproc_virtio { void *vdev_rsc; struct metal_io_region *vdev_rsc_io; rpvdev_notify_func notify; + rpvdev_wait_notified_func wait_notified; struct virtio_device vdev; struct metal_list node; }; @@ -62,6 +64,7 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, void *rsc, struct metal_io_region *rsc_io, void *priv, rpvdev_notify_func notify, + rpvdev_wait_notified_func wait_notified, virtio_dev_reset_cb rst_cb); /** diff --git a/lib/include/openamp/rpmsg.h b/lib/include/openamp/rpmsg.h index 8b8ec2ed1..60603ae07 100644 --- a/lib/include/openamp/rpmsg.h +++ b/lib/include/openamp/rpmsg.h @@ -42,6 +42,7 @@ extern "C" { #define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) #define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) #define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) +#define RPMSG_ERR_NXIO (RPMSG_ERROR_BASE - 8) struct rpmsg_endpoint; struct rpmsg_device; diff --git a/lib/include/openamp/rpmsg_virtio.h b/lib/include/openamp/rpmsg_virtio.h index 2f469e69b..f05e6b1ba 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ b/lib/include/openamp/rpmsg_virtio.h @@ -125,6 +125,15 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, callbacks); } +static inline int +rpmsg_virtio_wait_notified(struct rpmsg_virtio_device *rvdev, + struct virtqueue *vq) +{ + return rvdev->vdev->func->wait_notified ? + rvdev->vdev->func->wait_notified(rvdev->vdev, vq) : + RPMSG_ERR_NXIO; +} + /** * 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..8325c86b9 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_notified)(struct virtio_device *dev, struct virtqueue *vq); }; int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, diff --git a/lib/remoteproc/remoteproc.c b/lib/remoteproc/remoteproc.c index ba458bbe9..7b4cd1ee4 100644 --- a/lib/remoteproc/remoteproc.c +++ b/lib/remoteproc/remoteproc.c @@ -880,6 +880,16 @@ static int remoteproc_virtio_notify(void *priv, uint32_t id) return 0; } +static int remoteproc_virtio_wait_notified(void *priv, uint32_t id) +{ + struct remoteproc *rproc = priv; + + if (rproc->ops->wait_notified) + return rproc->ops->wait_notified(rproc, id); + + return 0; +} + struct virtio_device * remoteproc_create_virtio(struct remoteproc *rproc, int vdev_id, unsigned int role, @@ -918,6 +928,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, vdev = rproc_virtio_create_vdev(role, notifyid, vdev_rsc, vdev_rsc_io, rproc, remoteproc_virtio_notify, + remoteproc_virtio_wait_notified, rst_cb); if (!vdev) { metal_mutex_release(&rproc->lock); diff --git a/lib/remoteproc/remoteproc_virtio.c b/lib/remoteproc/remoteproc_virtio.c index ed9f33cbc..a9b01e154 100644 --- a/lib/remoteproc/remoteproc_virtio.c +++ b/lib/remoteproc/remoteproc_virtio.c @@ -30,6 +30,19 @@ static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) rpvdev->notify(rpvdev->priv, vring_info->notifyid); } +static int rproc_virtio_wait_notified(struct virtio_device *vdev, + struct virtqueue *vq) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vring_info; + unsigned int vq_id = vq->vq_queue_index; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vring_info = &vdev->vrings_info[vq_id]; + + return rpvdev->wait_notified(rpvdev->priv, vring_info->notifyid); +} + static unsigned char rproc_virtio_get_status(struct virtio_device *vdev) { struct remoteproc_virtio *rpvdev; @@ -179,6 +192,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_notified = rproc_virtio_wait_notified, #ifndef VIRTIO_SLAVE_ONLY /* * We suppose here that the vdev is in a shared memory so that can @@ -198,6 +212,7 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, void *rsc, struct metal_io_region *rsc_io, void *priv, rpvdev_notify_func notify, + rpvdev_wait_notified_func wait_notified, virtio_dev_reset_cb rst_cb) { struct remoteproc_virtio *rpvdev; @@ -233,6 +248,7 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, } rpvdev->notify = notify; + rpvdev->wait_notified = wait_notified; rpvdev->priv = priv; vdev->vrings_info = vrings_info; /* Assuming the shared memory has been mapped and registered if diff --git a/lib/rpmsg/rpmsg_virtio.c b/lib/rpmsg/rpmsg_virtio.c index e683bbe03..ad1bfc3ea 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ b/lib/rpmsg/rpmsg_virtio.c @@ -346,6 +346,13 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, metal_mutex_release(&rdev->lock); if (rp_hdr || !tick_count) break; + + status = rpmsg_virtio_wait_notified(rvdev, rvdev->rvq); + if (status == RPMSG_SUCCESS) + continue; + else if (status != RPMSG_ERR_NXIO) + break; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); tick_count--; }