rptun: pm_stay when send msg & pm_relax when all tx buffer returned

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2022-02-09 23:08:22 +08:00 committed by Petro Karashchenko
parent f0ba2f0286
commit 1c7e59eafa
2 changed files with 63 additions and 5 deletions

View File

@ -42,4 +42,14 @@ config RPTUN_LOCAL_CPUNAME
string "rptun local cpuname" string "rptun local cpuname"
default LIBC_HOSTNAME default LIBC_HOSTNAME
config RPTUN_PM
bool "rptun power management"
depends on PM
default n
---help---
If TX/RX buffer is supplied and powered by each CPU.
And when one CPU in DEEP sleep, then it's buffer will
goto RAM-retention mode, can't access from another CPU.
So, we provide this method to resolve this.
endif # RPTUN endif # RPTUN

View File

@ -35,6 +35,7 @@
#include <nuttx/semaphore.h> #include <nuttx/semaphore.h>
#include <nuttx/rptun/openamp.h> #include <nuttx/rptun/openamp.h>
#include <nuttx/rptun/rptun.h> #include <nuttx/rptun/rptun.h>
#include <nuttx/power/pm.h>
#include <nuttx/wqueue.h> #include <nuttx/wqueue.h>
#include <metal/utilities.h> #include <metal/utilities.h>
@ -71,12 +72,15 @@ struct rptun_priv_s
struct metal_list bind; struct metal_list bind;
struct metal_list node; struct metal_list node;
sem_t sem; sem_t sem;
unsigned long cmd;
#ifdef CONFIG_RPTUN_WORKQUEUE #ifdef CONFIG_RPTUN_WORKQUEUE
struct work_s work; struct work_s work;
#else #else
int tid; int tid;
#endif #endif
unsigned long cmd; #ifdef CONFIG_RPTUN_PM
bool stay;
#endif
}; };
struct rptun_bind_s struct rptun_bind_s
@ -250,6 +254,39 @@ static void rptun_unlock(void)
} }
} }
#ifdef CONFIG_RPTUN_PM
static inline void rptun_pm_action(FAR struct rptun_priv_s *priv,
bool stay)
{
irqstate_t flags;
flags = enter_critical_section();
if (stay && !priv->stay)
{
pm_stay(0, PM_IDLE);
priv->stay = true;
}
if (!stay && priv->stay && !rpmsg_buffer_nused(&priv->rvdev, false))
{
pm_relax(0, PM_IDLE);
priv->stay = false;
}
leave_critical_section(flags);
}
static inline void rptun_enable_rx_kick(FAR struct rptun_priv_s *priv)
{
virtqueue_enable_cb(priv->rvdev.svq);
}
#else
# define rptun_pm_action(priv, stay)
# define rptun_enable_rx_kick(priv)
#endif
static void rptun_worker(FAR void *arg) static void rptun_worker(FAR void *arg)
{ {
FAR struct rptun_priv_s *priv = arg; FAR struct rptun_priv_s *priv = arg;
@ -273,6 +310,8 @@ static void rptun_worker(FAR void *arg)
priv->cmd = RPTUNIOC_NONE; priv->cmd = RPTUNIOC_NONE;
remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL); remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL);
rptun_pm_action(priv, false);
} }
static void rptun_post(FAR struct rptun_priv_s *priv) static void rptun_post(FAR struct rptun_priv_s *priv)
@ -417,6 +456,14 @@ static int rptun_stop(FAR struct remoteproc *rproc)
static int rptun_notify(FAR struct remoteproc *rproc, uint32_t id) static int rptun_notify(FAR struct remoteproc *rproc, uint32_t id)
{ {
FAR struct rptun_priv_s *priv = rproc->priv; FAR struct rptun_priv_s *priv = rproc->priv;
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
FAR struct virtqueue *vq = rvdev->svq;
if (rvdev->vdev && vq &&
rvdev->vdev->vrings_info[vq->vq_queue_index].notifyid == id)
{
rptun_pm_action(priv, true);
}
RPTUN_NOTIFY(priv->dev, RPTUN_NOTIFY_ALL); RPTUN_NOTIFY(priv->dev, RPTUN_NOTIFY_ALL);
@ -743,6 +790,7 @@ static int rptun_dev_start(FAR struct remoteproc *rproc)
rptun_unlock(); rptun_unlock();
rptun_enable_rx_kick(priv);
return 0; return 0;
} }