mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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 <peng.fan@nxp.com> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
This commit is contained in:
parent
fbc0f319ce
commit
692e1bc96a
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user