[PATCH v3 01/10] mailbox: imx: Forward the timeout/ error in imx_mu_generic_tx()

Peng Fan peng.fan at oss.nxp.com
Wed Jun 17 18:50:20 PDT 2026


Hi Sebastian,

Thanks for your patch.

On Wed, Jun 17, 2026 at 08:55:26AM +0200, Sebastian Andrzej Siewior wrote:
>imx_mu_generic_tx() for the IMX_MU_TYPE_TXDB_V2 type polls on a register
>which may timeout and is recognized as an error. This error is siltently
>dropped and not dropped to the caller.
>
>Forward the error to the caller.
>
>Fixes: b5ef17917f3a7 ("mailbox: imx: fix TXDB_V2 channel race condition")
>Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
>---
> drivers/mailbox/imx-mailbox.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>index 246a9a9e39520..0028073be4a71 100644
>--- a/drivers/mailbox/imx-mailbox.c
>+++ b/drivers/mailbox/imx-mailbox.c
>@@ -227,6 +227,7 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
> 	u32 val;
> 	int ret, count;
> 
>+	ret = 0;
> 	switch (cp->type) {
> 	case IMX_MU_TYPE_TX:
> 		imx_mu_write(priv, *arg, priv->dcfg->xTR + cp->idx * 4);
>@@ -259,7 +260,7 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
> 		return -EINVAL;
> 	}
> 
>-	return 0;
>+	return ret;
> }

I just rethink about the logic here and rewrite the logic as below.
error code is propogated to caller and poll timeout are removed.
Please see whether it looks good for you or not.

[PATCH] mailbox: imx: make TXDB non-blocking and avoid polling in atomic context

The IMX_MU_TYPE_TXDB_V2 path currently writes to the GIR register and
then polls until the bit is cleared using readl_poll_timeout().

Because send_data() is invoked under spin_lock_irqsave() from the mailbox
core, meaning the polling loop can run in atomic context with interrupts
disabled. In the worst case, the current implementation may busy-wait for
up to 100ms, leading to excessive interrupt latency and potential soft
lockup warnings.

Moreover, the TXDB channel implements a doorbell mechanism, where the
sender only needs to trigger the event when the channel is idle. Waiting
for the GIR bit to clear after the write is no good with polling.

Fix this by:
  - Checking the GIR bit before issuing the write
  - Returning -EBUSY if the channel is still active
  - Removing the post-write polling loop

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/mailbox/imx-mailbox.c | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index 796ba983db29e..ed53bcffec673 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -241,7 +241,6 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
 {
 	u32 *arg = data;
 	u32 val;
-	int ret, count;
 
 	switch (cp->type) {
 	case IMX_MU_TYPE_TX:
@@ -253,22 +252,14 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
 		queue_work(system_bh_wq, &cp->txdb_work);
 		break;
 	case IMX_MU_TYPE_TXDB_V2:
+		val = readl(priv->base + priv->dcfg->xCR[IMX_MU_GCR]);
+		if (val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)) {
+			dev_info(priv->dev, "channel [%d] type: %d busy\n", cp->idx, cp->type);
+			return -EBUSY;
+		}
+
 		imx_mu_write(priv, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx),
 			     priv->dcfg->xCR[IMX_MU_GCR]);
-		ret = -ETIMEDOUT;
-		count = 0;
-		while (ret && (count < 10)) {
-			ret =
-			readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val,
-					   !(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)),
-					   0, 10000);
-
-			if (ret) {
-				dev_warn_ratelimited(priv->dev,
-						     "channel type: %d timeout, %d times, retry\n",
-						     cp->type, ++count);
-			}
-		}
 		break;
 	default:
 		dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
-- 
2.50.1

Thanks,
Peng

> 
> static int imx_mu_generic_rx(struct imx_mu_priv *priv,
>
>-- 
>2.53.0
>



More information about the linux-arm-kernel mailing list