mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
serial: 8250: Fix race condition in RTS-after-send handling
[ Upstream commit dedab69fd650ea74710b2e626e63fd35584ef773 ] Set em485->active_timer = NULL isn't always enough to take out the stop timer. While there is a check that it acts in the right state (i.e. waiting for RTS-after-send to pass after sending some chars) but the following might happen: - CPU1: some chars send, shifter becomes empty, stop tx timer armed - CPU0: more chars send before RTS-after-send expired - CPU0: shifter empty irq, port lock taken - CPU1: tx timer triggers, waits for port lock - CPU0: em485->active_timer = &em485->stop_tx_timer, hrtimer_start(), releases lock() - CPU1: get lock, see em485->active_timer == &em485->stop_tx_timer, tear down RTS too early This fix bases on research done by Steffen Trumtrar. Fixes: b86f86e8e7c5 ("serial: 8250: fix potential deadlock in rs485-mode") Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20220215160236.344236-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
1345af488a
commit
48db011da8
@ -1596,6 +1596,18 @@ static inline void start_tx_rs485(struct uart_port *port)
|
||||
if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
|
||||
serial8250_stop_rx(&up->port);
|
||||
|
||||
/*
|
||||
* While serial8250_em485_handle_stop_tx() is a noop if
|
||||
* em485->active_timer != &em485->stop_tx_timer, it might happen that
|
||||
* the timer is still armed and triggers only after the current bunch of
|
||||
* chars is send and em485->active_timer == &em485->stop_tx_timer again.
|
||||
* So cancel the timer. There is still a theoretical race condition if
|
||||
* the timer is already running and only comes around to check for
|
||||
* em485->active_timer when &em485->stop_tx_timer is armed again.
|
||||
*/
|
||||
if (em485->active_timer == &em485->stop_tx_timer)
|
||||
hrtimer_try_to_cancel(&em485->stop_tx_timer);
|
||||
|
||||
em485->active_timer = NULL;
|
||||
|
||||
mcr = serial8250_in_MCR(up);
|
||||
|
Loading…
x
Reference in New Issue
Block a user