提交 680d5826 编写于 作者: P Phil Elwell 提交者: Zheng Zengkai

Revert "mailbox: avoid timer start from callback"

raspberrypi inclusion
category: feature
bugzilla: 50432

--------------------------------

This reverts commit c7dacf5b.

The Pi 400 shutdown/poweroff mechanism relies on being able to set
a GPIO on the expander in the pm_power_off handler, something that
requires two mailbox calls - GET_GPIO_STATE and SET_GPIO_STATE. A
recent kernel change introduces a reasonable possibility that the
GET call doesn't completes, and bisecting led to a commit from
October that changes the timer usage of the mailbox.

My theory is that there is a race condition in the new code that breaks
the poll timer, but that it normally goes unnoticed because subsequent
mailbox activity wakes it up again. The power-off mailbox calls happen
at a time when other subsystems have been shut down, so if one of them
fails then there is nothing to allow it to recover.

See: https://github.com/raspberrypi/linux/issues/3941Signed-off-by: NPhil Elwell <phil@raspberrypi.com>
Signed-off-by: NFang Yafen <yafen@iscas.ac.cn>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 ce67e99e
...@@ -82,12 +82,9 @@ static void msg_submit(struct mbox_chan *chan) ...@@ -82,12 +82,9 @@ static void msg_submit(struct mbox_chan *chan)
exit: exit:
spin_unlock_irqrestore(&chan->lock, flags); spin_unlock_irqrestore(&chan->lock, flags);
/* kick start the timer immediately to avoid delays */ if (!err && (chan->txdone_method & TXDONE_BY_POLL))
if (!err && (chan->txdone_method & TXDONE_BY_POLL)) { /* kick start the timer immediately to avoid delays */
/* but only if not already active */ hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
if (!hrtimer_active(&chan->mbox->poll_hrt))
hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
}
} }
static void tx_tick(struct mbox_chan *chan, int r) static void tx_tick(struct mbox_chan *chan, int r)
...@@ -125,10 +122,11 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer) ...@@ -125,10 +122,11 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
struct mbox_chan *chan = &mbox->chans[i]; struct mbox_chan *chan = &mbox->chans[i];
if (chan->active_req && chan->cl) { if (chan->active_req && chan->cl) {
resched = true;
txdone = chan->mbox->ops->last_tx_done(chan); txdone = chan->mbox->ops->last_tx_done(chan);
if (txdone) if (txdone)
tx_tick(chan, 0); tx_tick(chan, 0);
else
resched = true;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册