From 36d1eee8b0c531cd0106809df6ed91a138ddc10a Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Fri, 8 Dec 2017 19:36:13 +0000 Subject: [PATCH] drivers: mailbox: fix race resulting in multiple message submission The mailbox sends a request to the controller and the tx_done callback received for that request clears the active_req pointer. The callback sends the next request in the queue, if there is one. When a controller is busy and cannot accept any more requests until the interrupt is cleared, it would return -EAGAIN. The mailbox controller must unlock its spinlock and retry again. Change-Id: Id58c7365be8c6bfc7f90fe9445c88c1246d2d7f8 Signed-off-by: Lina Iyer --- drivers/mailbox/mailbox.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c index 0b821a5b2db8..9301cacc7305 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -50,7 +50,7 @@ static int add_to_rbuf(struct mbox_chan *chan, void *mssg) return idx; } -static void msg_submit(struct mbox_chan *chan) +static int __msg_submit(struct mbox_chan *chan) { unsigned count, idx; unsigned long flags; @@ -82,6 +82,24 @@ static void msg_submit(struct mbox_chan *chan) exit: spin_unlock_irqrestore(&chan->lock, flags); + return err; +} + +static void msg_submit(struct mbox_chan *chan) +{ + int err = 0; + + /* + * If the controller returns -EAGAIN, then it means, our spinlock + * here is preventing the controller from receiving its interrupt, + * that would help clear the controller channels that are currently + * blocked waiting on the interrupt response. + * Retry again. + */ + do { + err = __msg_submit(chan); + } while (err == -EAGAIN); + if (!err && (chan->txdone_method & TXDONE_BY_POLL)) /* kick start the timer immediately to avoid delays */ hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);