From ddc209c9475a2822ffe5d18441bd01718acdbc11 Mon Sep 17 00:00:00 2001 From: ligd Date: Fri, 29 Jul 2022 22:57:23 +0800 Subject: [PATCH 4/9] openamp: add new ops notify_wait() support This can avoid looping check tx buffer Change-Id: Ie340ed06c306ce978ff165aacaf5b830e3645af8 Signed-off-by: ligd --- lib/include/openamp/remoteproc.h | 12 ++++++++++++ lib/include/openamp/remoteproc_virtio.h | 2 ++ 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 | 14 ++++++++++++++ lib/rpmsg/rpmsg_virtio.c | 7 +++++++ 8 files changed, 57 insertions(+) diff --git a/lib/include/openamp/remoteproc.h open-amp/lib/include/openamp/remoteproc.h index d1efab85..f6554404 100644 --- a/lib/include/openamp/remoteproc.h +++ open-amp/lib/include/openamp/remoteproc.h @@ -428,6 +428,18 @@ struct remoteproc_ops { int (*stop)(struct remoteproc *rproc); int (*shutdown)(struct remoteproc *rproc); int (*notify)(struct remoteproc *rproc, uint32_t id); + /** + * notify_wait + * + * Wait for remote notified, when there is no TX buffer anymore. + * Set to NULL means use usleep to wait TX buffer available. + * + * @rproc - pointer to remoteproc instance + * @id - the notifyid + * + * return 0 means there is notify available, otherwise negative value. + */ + int (*notify_wait)(struct remoteproc *rproc, uint32_t id); /** * get_mem * diff --git a/lib/include/openamp/remoteproc_virtio.h open-amp/lib/include/openamp/remoteproc_virtio.h index 6609a1fd..e65488d5 100644 --- a/lib/include/openamp/remoteproc_virtio.h +++ open-amp/lib/include/openamp/remoteproc_virtio.h @@ -25,6 +25,7 @@ extern "C" { /* define vdev notification function user should implement */ typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); +typedef int (*rpvdev_notify_wait)(void *priv, uint32_t id); /** * struct remoteproc_virtio @@ -40,6 +41,7 @@ struct remoteproc_virtio { void *vdev_rsc; struct metal_io_region *vdev_rsc_io; rpvdev_notify_func notify; + rpvdev_notify_wait notify_wait; struct virtio_device vdev; struct metal_list node; }; diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h index dbe42ea6..14440e20 100644 --- a/lib/include/openamp/rpmsg.h +++ open-amp/lib/include/openamp/rpmsg.h @@ -50,6 +50,7 @@ extern "C" { #define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) #define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) #define RPMSG_ERR_PERM (RPMSG_ERROR_BASE - 8) +#define RPMSG_ERR_NXIO (RPMSG_ERROR_BASE - 9) struct rpmsg_endpoint; struct rpmsg_device; diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h index 0b22e840..11cb6df9 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ open-amp/lib/include/openamp/rpmsg_virtio.h @@ -148,6 +148,15 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, callbacks); } +static inline int +rpmsg_virtio_notify_wait(struct rpmsg_virtio_device *rvdev, + struct virtqueue *vq) +{ + return rvdev->vdev->func->notify_wait ? + rvdev->vdev->func->notify_wait(rvdev->vdev, vq) : + RPMSG_ERR_NXIO; +} + /** * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size * diff --git a/lib/include/openamp/virtio.h open-amp/lib/include/openamp/virtio.h index 916132b4..0303a5b3 100644 --- a/lib/include/openamp/virtio.h +++ open-amp/lib/include/openamp/virtio.h @@ -162,6 +162,7 @@ struct virtio_dispatch { void *src, int length); void (*reset_device)(struct virtio_device *dev); void (*notify)(struct virtqueue *vq); + int (*notify_wait)(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 open-amp/lib/remoteproc/remoteproc.c index f7f9f2df..001b11bf 100644 --- a/lib/remoteproc/remoteproc.c +++ open-amp/lib/remoteproc/remoteproc.c @@ -899,6 +899,16 @@ static int remoteproc_virtio_notify(void *priv, uint32_t id) return 0; } +static int remoteproc_virtio_notify_wait(void *priv, uint32_t id) +{ + struct remoteproc *rproc = priv; + + if (rproc->ops->notify_wait) + return rproc->ops->notify_wait(rproc, id); + + return 0; +} + struct virtio_device * remoteproc_create_virtio(struct remoteproc *rproc, int vdev_id, unsigned int role, @@ -957,6 +967,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, rproc_virtio_wait_remote_ready(vdev); rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + rpvdev->notify_wait = remoteproc_virtio_notify_wait; metal_list_add_tail(&rproc->vdevs, &rpvdev->node); num_vrings = vdev_rsc->num_of_vrings; diff --git a/lib/remoteproc/remoteproc_virtio.c open-amp/lib/remoteproc/remoteproc_virtio.c index 169e5b5f..4375c4c3 100644 --- a/lib/remoteproc/remoteproc_virtio.c +++ open-amp/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_notify_wait(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->notify_wait(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, + .notify_wait = rproc_virtio_notify_wait, #ifndef VIRTIO_DEVICE_ONLY /* * We suppose here that the vdev is in a shared memory so that can diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c index c56e0cea..4960aa8a 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c @@ -373,6 +373,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_notify_wait(rvdev, rvdev->rvq); + if (status == RPMSG_SUCCESS) + continue; + else if (status != RPMSG_ERR_NXIO) + break; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); tick_count--; } -- 2.25.1