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);

Reply via email to