From: Sebastian Andrzej Siewior Date: Wed, 17 Jun 2026 06:55:31 +0000 (+0200) Subject: mailbox: imx: Start splitting the IRQ handler in primary and threaded handler X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=692e1bc96a5dc7d5c43d937c2a50b56303544dea;p=thirdparty%2Fkernel%2Flinux.git mailbox: imx: Start splitting the IRQ handler in primary and threaded handler Split the mailbox irq handling into a primary handler (imx_mu_isr()) and a threaded handler (imx_mu_isr_th()). The primary handler masks the interrupt event so the threaded handler can run without raising the interrupt again. The goal here is to invoke the mailbox core functions (such as mbox_chan_received_data(), mbox_chan_txdone()) in preemptible context which is made possible by using an threaded interrupt handler. This in turn means that mailbox's client callbacks are invoked in preemptible context, too. This then allows the mailbox client callback to skip an indirection via a workqueue if it requries preemptible callback. As a first step, prepare the logic and move TX handling part. Reviewed-by: Peng Fan Reviewed-by: Mathieu Poirier Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Jassi Brar --- diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c index 408cd083c64e..87acc43cb99c 100644 --- a/drivers/mailbox/imx-mailbox.c +++ b/drivers/mailbox/imx-mailbox.c @@ -540,11 +540,31 @@ static void imx_mu_txdb_work(struct work_struct *t) mbox_chan_txdone(cp->chan, 0); } +static irqreturn_t imx_mu_isr_th(int irq, void *p) +{ + struct mbox_chan *chan = p; + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); + struct imx_mu_con_priv *cp = chan->con_priv; + + switch (cp->type) { + case IMX_MU_TYPE_TX: + mbox_chan_txdone(chan, 0); + break; + + default: + dev_warn_ratelimited(priv->dev, "Unhandled channel type %d\n", + cp->type); + return IRQ_NONE; + } + return IRQ_HANDLED; +} + static irqreturn_t imx_mu_isr(int irq, void *p) { struct mbox_chan *chan = p; struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); struct imx_mu_con_priv *cp = chan->con_priv; + irqreturn_t ret = IRQ_HANDLED; u32 val, ctrl; switch (cp->type) { @@ -580,7 +600,7 @@ static irqreturn_t imx_mu_isr(int irq, void *p) if ((val == IMX_MU_xSR_TEn(priv->dcfg->type, cp->idx)) && (cp->type == IMX_MU_TYPE_TX)) { imx_mu_xcr_rmw(priv, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx)); - mbox_chan_txdone(chan, 0); + ret = IRQ_WAKE_THREAD; } else if ((val == IMX_MU_xSR_RFn(priv->dcfg->type, cp->idx)) && (cp->type == IMX_MU_TYPE_RX)) { priv->dcfg->rx(priv, cp); @@ -595,7 +615,7 @@ static irqreturn_t imx_mu_isr(int irq, void *p) if (priv->suspend) pm_system_wakeup(); - return IRQ_HANDLED; + return ret; } static int imx_mu_send_data(struct mbox_chan *chan, void *data) @@ -630,7 +650,8 @@ static int imx_mu_startup(struct mbox_chan *chan) if (!(priv->dcfg->type & IMX_MU_V2_IRQ)) irq_flag |= IRQF_SHARED; - ret = request_irq(priv->irq[cp->type], imx_mu_isr, irq_flag, cp->irq_desc, chan); + ret = request_threaded_irq(priv->irq[cp->type], imx_mu_isr, imx_mu_isr_th, + irq_flag, cp->irq_desc, chan); if (ret) { dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq[cp->type]); return ret;