Use generic mbox_bind_client() to bind omap mailbox channel to a client. mbox_bind_client is identical to the replaced lines, except that it: - Does the operation under con_mutex which prevents possible races in removal path - Sets TXDONE_BY_ACK if pcc uses TXDONE_BY_POLL and the client knows when tx is done. TXDONE_BY_ACK is already set if there's no interrupt, so this is not applicable. - Calls chan->mbox->ops->startup. This is usecase for requesting irq: move the devm_request_irq into the startup callback and unregister it in the shutdown path. Signed-off-by: Elliot Berman <quic_eberman@xxxxxxxxxxx> --- drivers/mailbox/pcc.c | 82 ++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 105d46c9801b..3a025415c5d5 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -283,7 +283,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) struct pcc_chan_info *pchan; struct mbox_chan *chan; struct device *dev; - unsigned long flags; + int rc; if (subspace_id < 0 || subspace_id >= pcc_chan_count) return ERR_PTR(-ENOENT); @@ -296,30 +296,9 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) } dev = chan->mbox->dev; - spin_lock_irqsave(&chan->lock, flags); - chan->msg_free = 0; - chan->msg_count = 0; - chan->active_req = NULL; - chan->cl = cl; - init_completion(&chan->tx_complete); - - if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) - chan->txdone_method = TXDONE_BY_ACK; - - spin_unlock_irqrestore(&chan->lock, flags); - - if (pchan->plat_irq > 0) { - int rc; - - rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0, - MBOX_IRQ_NAME, chan); - if (unlikely(rc)) { - dev_err(dev, "failed to register PCC interrupt %d\n", - pchan->plat_irq); - pcc_mbox_free_channel(&pchan->chan); - return ERR_PTR(rc); - } - } + rc = mbox_bind_client(chan, cl); + if (rc) + return ERR_PTR(rc); return &pchan->chan; } @@ -333,23 +312,12 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel); */ void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) { - struct pcc_chan_info *pchan_info = to_pcc_chan_info(pchan); struct mbox_chan *chan = pchan->mchan; - unsigned long flags; if (!chan || !chan->cl) return; - if (pchan_info->plat_irq > 0) - devm_free_irq(chan->mbox->dev, pchan_info->plat_irq, chan); - - spin_lock_irqsave(&chan->lock, flags); - chan->cl = NULL; - chan->active_req = NULL; - if (chan->txdone_method == TXDONE_BY_ACK) - chan->txdone_method = TXDONE_BY_POLL; - - spin_unlock_irqrestore(&chan->lock, flags); + mbox_free_channel(chan); } EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); @@ -377,8 +345,48 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) return pcc_chan_reg_read_modify_write(&pchan->db); } +/** + * pcc_startup - Called from Mailbox Controller code. Used here + * to request the interrupt. + * @chan: Pointer to Mailbox channel to startup. + * + * Return: Err if something failed else 0 for success. + */ +int pcc_startup(struct mbox_chan *chan) +{ + struct pcc_chan_info *pchan = chan->con_priv; + int rc; + + if (pchan->plat_irq > 0) { + rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, + MBOX_IRQ_NAME, chan); + if (unlikely(rc)) { + dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", + pchan->plat_irq); + return rc; + } + } + + return 0; +} + +/** + * pcc_shutdown - Called from Mailbox Controller code. Used here + * to free the interrupt. + * @chan: Pointer to Mailbox channel to shutdown. + */ +void pcc_shutdown(struct mbox_chan *chan) +{ + struct pcc_chan_info *pchan = chan->con_priv; + + if (pchan->plat_irq > 0) + devm_free_irq(chan->mbox->dev, pchan->plat_irq, chan); +} + static const struct mbox_chan_ops pcc_chan_ops = { .send_data = pcc_send_data, + .startup = pcc_startup, + .shutdown = pcc_shutdown, }; /** -- 2.39.1