bcm27xx: import latest patches from the RPi foundation
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-1014-Revert-mailbox-avoid-timer-start-from-callback.patch
1 From 2b7fcd18b15d9cc7b2e68deb77f4e0acfa904c41 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Tue, 3 Nov 2020 10:13:48 +0000
4 Subject: [PATCH] Revert "mailbox: avoid timer start from callback"
5
6 This reverts commit 6dc15642c8b830d384fd3e6c9ea63144202b8932.
7
8 The Pi 400 shutdown/poweroff mechanism relies on being able to set
9 a GPIO on the expander in the pm_power_off handler, something that
10 requires two mailbox calls - GET_GPIO_STATE and SET_GPIO_STATE. A
11 recent kernel change introduces a reasonable possibility that the
12 GET call doesn't completes, and bisecting led to a commit from
13 October that changes the timer usage of the mailbox.
14
15 My theory is that there is a race condition in the new code that breaks
16 the poll timer, but that it normally goes unnoticed because subsequent
17 mailbox activity wakes it up again. The power-off mailbox calls happen
18 at a time when other subsystems have been shut down, so if one of them
19 fails then there is nothing to allow it to recover.
20
21 Revert 6dc15642 as (at least) a workaround.
22
23 See: https://github.com/raspberrypi/linux/issues/3941
24
25 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
26 ---
27 drivers/mailbox/mailbox.c | 12 +++++-------
28 1 file changed, 5 insertions(+), 7 deletions(-)
29
30 --- a/drivers/mailbox/mailbox.c
31 +++ b/drivers/mailbox/mailbox.c
32 @@ -82,12 +82,9 @@ static void msg_submit(struct mbox_chan
33 exit:
34 spin_unlock_irqrestore(&chan->lock, flags);
35
36 - /* kick start the timer immediately to avoid delays */
37 - if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
38 - /* but only if not already active */
39 - if (!hrtimer_active(&chan->mbox->poll_hrt))
40 - hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
41 - }
42 + if (!err && (chan->txdone_method & TXDONE_BY_POLL))
43 + /* kick start the timer immediately to avoid delays */
44 + hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
45 }
46
47 static void tx_tick(struct mbox_chan *chan, int r)
48 @@ -125,10 +122,11 @@ static enum hrtimer_restart txdone_hrtim
49 struct mbox_chan *chan = &mbox->chans[i];
50
51 if (chan->active_req && chan->cl) {
52 - resched = true;
53 txdone = chan->mbox->ops->last_tx_done(chan);
54 if (txdone)
55 tx_tick(chan, 0);
56 + else
57 + resched = true;
58 }
59 }
60