summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShenwei Wang <shenwei.wang@nxp.com>2021-05-04 08:28:14 -0500
committerDenys Drozdov <denys.drozdov@toradex.com>2021-07-15 13:54:56 +0300
commita4aacc8f17022d0485c45810f34d82fe889cbc42 (patch)
treef86f50238086e46e4582bc317a330972afccc136
parent236620c5b121c73dce83870fabbaa144cb21211d (diff)
MPSDK-172 remoteproc: imx_rproc: Re-building communication channels when a remote crashes
When the crash of a remote proc is detected, the physical communication channels may get corrupted or reset, and it will impact the subsequent transfers of rpmsg message. So the communication channels should be re-built when a remote crash is detected. Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com> Reviewed-by: Frank Li <frank.li@nxp.com>
-rw-r--r--drivers/remoteproc/imx_rproc.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index e913c5efcdbf..8537eccfd73a 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -365,6 +365,76 @@ bool imx_rproc_ready(struct rproc *rproc)
return true;
}
+static int imx_rproc_rebuild_channels(struct rproc *rproc)
+{
+ struct imx_rproc *priv = rproc->priv;
+ struct mbox_client *cl = &priv->cl;
+ struct device *dev = priv->dev;
+ int ret = 0;
+
+ if (!priv->tx_ch) {
+ priv->tx_ch = mbox_request_channel_byname(cl, "tx");
+ if (IS_ERR(priv->tx_ch)) {
+ ret = PTR_ERR(priv->tx_ch);
+ dev_err(dev, "failed to restart tx chan %d\n", ret);
+ priv->tx_ch = NULL;
+
+ goto err_exit;
+ }
+ }
+
+ if (!priv->rx_ch) {
+ priv->rx_ch = mbox_request_channel_byname(cl, "rx");
+ if (IS_ERR(priv->rx_ch)) {
+ ret = PTR_ERR(priv->rx_ch);
+ dev_err(dev, "failed to restart rx chan %d\n", ret);
+ priv->rx_ch = NULL;
+
+ goto err_exit;
+ }
+ }
+
+ if (!priv->rxdb_ch) {
+ priv->rxdb_ch = mbox_request_channel_byname(cl, "rxdb");
+ if (IS_ERR(priv->rxdb_ch)) {
+ ret = PTR_ERR(priv->rxdb_ch);
+ dev_err(dev, "failed to restart rxdb chan %d\n", ret);
+ priv->rxdb_ch = NULL;
+
+ goto err_exit;
+ }
+ }
+
+ /* txdb is optional */
+ if (!priv->txdb_ch) {
+ priv->txdb_ch = mbox_request_channel_byname(cl, "txdb");
+ if (IS_ERR(priv->txdb_ch))
+ priv->txdb_ch = NULL;
+ }
+
+err_exit:
+ return ret;
+}
+
+static void imx_rproc_free_channels(struct rproc *rproc)
+{
+ struct imx_rproc *priv = rproc->priv;
+ __u32 mmsg;
+
+ if (priv->txdb_ch)
+ mbox_send_message(priv->txdb_ch, (void *)&mmsg);
+
+ mbox_free_channel(priv->tx_ch);
+ mbox_free_channel(priv->rx_ch);
+ mbox_free_channel(priv->rxdb_ch);
+ mbox_free_channel(priv->txdb_ch);
+
+ priv->tx_ch = NULL;
+ priv->rx_ch = NULL;
+ priv->rxdb_ch = NULL;
+ priv->txdb_ch = NULL;
+}
+
static int imx_rproc_start(struct rproc *rproc)
{
struct imx_rproc *priv = rproc->priv;
@@ -376,6 +446,10 @@ static int imx_rproc_start(struct rproc *rproc)
if (priv->ipc_only) {
dev_info(dev, "%s: IPC only\n", __func__);
+ ret = imx_rproc_rebuild_channels(rproc);
+ if (ret < 0)
+ return -EINVAL;
+
/* To partition M4, we need block userspace stop/start */
if (priv->skip_fw_load_recovery) {
priv->skip_fw_load_recovery = false;
@@ -451,6 +525,8 @@ static int imx_rproc_stop(struct rproc *rproc)
if (priv->ipc_only) {
dev_info(dev, "%s: IPC only\n", __func__);
+ imx_rproc_free_channels(rproc);
+
/*
* TO i.MX8 Paritioned M4, M4 reboot is handled by itself,
* so we still keep early boot and skip fw load flag