diff options
author | Anson Huang <Anson.Huang@nxp.com> | 2020-04-23 16:52:40 +0800 |
---|---|---|
committer | Anson Huang <Anson.Huang@nxp.com> | 2020-04-24 09:53:34 +0800 |
commit | 05d03f6ef4da50f42669904bd640dea1268290dd (patch) | |
tree | 01c704797b0cd0543a25cab7595b21b99dff85e1 /drivers/mailbox | |
parent | 972cc03234a99d42cf28ecd1dc89b281096d6ff3 (diff) |
MLK-23835 mailbox: imx: Only restore MU settings when context lost
During noirq suspend/resume, if MU context is NOT lost, such
as freeze mode suspend, when resume, there could be 2 CPUs
calling IPC, 1 CPU is in charge of handling wakeup event, the
other CPU is busy with device resume flow, the MU TIE could
be set during IPC called by the CPU handling wakeup event,
then the noirq resume callback in mailbox will be called by
the CPU executing device resume, it could overwrite the MU
settings and clear TIE by mistake, then cause the TX never
finish and IPC mutex lock never released, and system will
freeze, all CPUs are in idle and never wake up.
To avoid this issue, we should ONLY restore the MU settings
when its context is lost.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Reported-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Jacky Bai <ping.bai@nxp.com>
Diffstat (limited to 'drivers/mailbox')
-rw-r--r-- | drivers/mailbox/imx-mailbox.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c index c711165e3207..2a8c3e8aefb5 100644 --- a/drivers/mailbox/imx-mailbox.c +++ b/drivers/mailbox/imx-mailbox.c @@ -628,7 +628,16 @@ static int imx_mu_resume_noirq(struct device *dev) { struct imx_mu_priv *priv = dev_get_drvdata(dev); - imx_mu_write(priv, priv->xcr, priv->dcfg->xCR); + /* + * ONLY restore MU when context lost, the TIE could + * be set during noirq resume as there is MU data + * communication going on, and restore the saved + * value will overwrite the TIE and cause MU data + * send failed, may lead to system freeze. This issue + * is observed by testing freeze mode suspend. + */ + if (!imx_mu_read(priv, priv->dcfg->xCR)) + imx_mu_write(priv, priv->xcr, priv->dcfg->xCR); return 0; } |