[PATCH v2 5/9] mailbox: imx: Start splitting the IRQ handler in primary and threaded handler
Sebastian Andrzej Siewior
bigeasy at linutronix.de
Wed Jun 3 06:05:08 PDT 2026
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 threaded handler can invoke the actuall callback in
preemtible context.
As a first step, prepare the logic and move TX handling part.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
drivers/mailbox/imx-mailbox.c | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index d1de07cc0ed62..006aa76b74b62 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -81,6 +81,7 @@ struct imx_mu_con_priv {
struct mbox_chan *chan;
struct work_struct txdb_work;
bool shutdown;
+ bool pending;
};
struct imx_mu_priv {
@@ -539,11 +540,35 @@ 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;
+
+ if (!cp->pending)
+ return IRQ_NONE;
+
+ switch (cp->type) {
+ case IMX_MU_TYPE_TX:
+ cp->pending = false;
+ 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) {
@@ -579,7 +604,8 @@ 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);
+ cp->pending = true;
+ 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);
@@ -594,7 +620,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)
@@ -629,7 +655,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;
--
2.53.0
More information about the linux-arm-kernel
mailing list