This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit a95bb2aef2bb9b8b8b33b24fec7bc9282b11f4bd Author: Bowen Wang <[email protected]> AuthorDate: Sun Apr 27 11:02:42 2025 +0800 drivers/rpmsg/rpmsg_virtio: fix the PM wakelock handling - Do not relax the PM wakelock when waking up tx; it is relaxed in the tx done callback once the peer has returned the buffers. - Update headrx during initialization so the rx side processes what the peer queued before the device came up. - Do not call virtqueue_enable_cb()/virtqueue_disable_cb() on the tx virtqueue while waiting for a tx buffer, which may touch the peer's memory. - Enable the tx virtqueue callback when the device is initialized, before the rpmsg services are created. Signed-off-by: Bowen Wang <[email protected]> --- drivers/rpmsg/rpmsg_virtio.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/rpmsg/rpmsg_virtio.c b/drivers/rpmsg/rpmsg_virtio.c index f975fb4a0f9..db17cb55696 100644 --- a/drivers/rpmsg/rpmsg_virtio.c +++ b/drivers/rpmsg/rpmsg_virtio.c @@ -286,13 +286,6 @@ static void rpmsg_virtio_wakeup_tx(FAR struct rpmsg_virtio_priv_s *priv) { nxsem_post(&priv->semtx); } - - /* rpmsg_virtio_wakeup_tx() called normally means the tx buffer has been - * returned by peer, so call rpmsg_virtio_pm_action(false) to enter - * lowe power mode when there is no pending tx buffer. - */ - - rpmsg_virtio_pm_action(priv, false); } /**************************************************************************** @@ -452,13 +445,11 @@ static void rpmsg_virtio_dump(FAR struct rpmsg_s *rpmsg) } /**************************************************************************** - * Name: rpmsg_virtio_rx_callback + * Name: rpmsg_virtio_update_rx ****************************************************************************/ -static void rpmsg_virtio_rx_callback(FAR struct virtqueue *vq) +static void rpmsg_virtio_update_rx(FAR struct rpmsg_virtio_priv_s *priv) { - FAR struct rpmsg_virtio_priv_s *priv = - metal_container_of(vq->vq_dev->priv, struct rpmsg_virtio_priv_s, rvdev); FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev; FAR struct virtqueue *rvq = rvdev->rvq; @@ -472,7 +463,18 @@ static void rpmsg_virtio_rx_callback(FAR struct virtqueue *vq) RPMSG_VIRTIO_INVALIDATE(rvq->vq_ring.avail->idx); priv->headrx = rvq->vq_ring.avail->idx; } +} +/**************************************************************************** + * Name: rpmsg_virtio_rx_callback + ****************************************************************************/ + +static void rpmsg_virtio_rx_callback(FAR struct virtqueue *vq) +{ + FAR struct rpmsg_virtio_priv_s *priv = + metal_container_of(vq->vq_dev->priv, struct rpmsg_virtio_priv_s, rvdev); + + rpmsg_virtio_update_rx(priv); rpmsg_virtio_wakeup_rx(priv); } @@ -486,6 +488,12 @@ static void rpmsg_virtio_tx_callback(FAR struct virtqueue *vq) metal_container_of(vq->vq_dev->priv, struct rpmsg_virtio_priv_s, rvdev); rpmsg_virtio_wakeup_tx(priv); + + /* rpmsg_virtio_tx_callback() called normally means the tx buffer has been + * returned by peer, so call rpmsg_virtio_pm_action(false) to enter to + * low power mode when all the tx buffers have been returned. + */ + rpmsg_virtio_pm_action(priv, false); } @@ -524,9 +532,7 @@ static int rpmsg_virtio_notify_wait(FAR struct rpmsg_device *rdev, /* Wait to wakeup */ - virtqueue_enable_cb(priv->rvdev.svq); nxsem_tickwait(&priv->semtx, MSEC2TICK(RPMSG_VIRTIO_TIMEOUT_MS)); - virtqueue_disable_cb(priv->rvdev.svq); rpmsg_virtio_rx_worker(priv); return 0; @@ -607,8 +613,15 @@ static int rpmsg_virtio_start(FAR struct rpmsg_virtio_priv_s *priv) /* Wake up the rx thread to process message */ + rpmsg_virtio_update_rx(priv); rpmsg_virtio_wakeup_rx(priv); + /* Open tx buffer return callback before the services created below can + * wait for a tx buffer. + */ + + virtqueue_enable_cb(priv->rvdev.svq); + /* Broadcast device_created to all registers */ rpmsg_device_created(&priv->rpmsg);
