diff options
author | Shenwei Wang <shenwei.wang@nxp.com> | 2021-05-04 08:28:14 -0500 |
---|---|---|
committer | Denys Drozdov <denys.drozdov@toradex.com> | 2021-07-15 13:54:56 +0300 |
commit | a4aacc8f17022d0485c45810f34d82fe889cbc42 (patch) | |
tree | f86f50238086e46e4582bc317a330972afccc136 | |
parent | 236620c5b121c73dce83870fabbaa144cb21211d (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.c | 76 |
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 |