Skip to content

Commit c7dacf5

Browse files
committed
mailbox: avoid timer start from callback
If the txdone is done by polling, it is possible for msg_submit() to start the timer while txdone_hrtimer() callback is running. If the timer needs recheduling, it could already be enqueued by the time hrtimer_forward_now() is called, leading hrtimer to loudly complain. WARNING: CPU: 3 PID: 74 at kernel/time/hrtimer.c:932 hrtimer_forward+0xc4/0x110 CPU: 3 PID: 74 Comm: kworker/u8:1 Not tainted 5.9.0-rc2-00236-gd3520067d01c-dirty #5 Hardware name: Libre Computer AML-S805X-AC (DT) Workqueue: events_freezable_power_ thermal_zone_device_check pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--) pc : hrtimer_forward+0xc4/0x110 lr : txdone_hrtimer+0xf8/0x118 [...] This can be fixed by not starting the timer from the callback path. Which requires the timer reloading as long as any message is queued on the channel, and not just when current tx is not done yet. Fixes: 0cc6794 ("mailbox: switch to hrtimer for tx_complete polling") Reported-by: Da Xue <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Tested-by: Sudeep Holla <[email protected]> Acked-by: Jerome Brunet <[email protected]> Tested-by: Jerome Brunet <[email protected]> Signed-off-by: Jassi Brar <[email protected]>
1 parent 558e4c3 commit c7dacf5

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/mailbox/mailbox.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,12 @@ static void msg_submit(struct mbox_chan *chan)
8282
exit:
8383
spin_unlock_irqrestore(&chan->lock, flags);
8484

85-
if (!err && (chan->txdone_method & TXDONE_BY_POLL))
86-
/* kick start the timer immediately to avoid delays */
87-
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
85+
/* kick start the timer immediately to avoid delays */
86+
if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
87+
/* but only if not already active */
88+
if (!hrtimer_active(&chan->mbox->poll_hrt))
89+
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
90+
}
8891
}
8992

9093
static void tx_tick(struct mbox_chan *chan, int r)
@@ -122,11 +125,10 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
122125
struct mbox_chan *chan = &mbox->chans[i];
123126

124127
if (chan->active_req && chan->cl) {
128+
resched = true;
125129
txdone = chan->mbox->ops->last_tx_done(chan);
126130
if (txdone)
127131
tx_tick(chan, 0);
128-
else
129-
resched = true;
130132
}
131133
}
132134

0 commit comments

Comments
 (0)