summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Melin <tomas.melin@vaisala.com>2017-10-27 15:16:30 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-05-22 10:57:43 +0200
commitf7d0f2440978f7d5e72b6f86af01e49f6e545690 (patch)
tree4b8f389fba99788b50f1f4b08e1f8bae19f5a042
parente7f7cf9b93bd87c6ff91d733923a5bccf35c16d9 (diff)
downloadlinux-f7d0f2440978f7d5e72b6f86af01e49f6e545690.tar.gz
linux-f7d0f2440978f7d5e72b6f86af01e49f6e545690.tar.bz2
linux-f7d0f2440978f7d5e72b6f86af01e49f6e545690.zip
serial: 8250: fix potential deadlock in rs485-mode
[ Upstream commit b86f86e8e7c5264bb8f5835d60f9ec840d9f5a7a ] Canceling hrtimer when holding uart spinlock can deadlock. CPU0: syscall write -> get uart port spinlock -> write uart -> start_tx_rs485 -> hrtimer_cancel -> wait for hrtimer callback to finish CPU1: hrtimer IRQ -> run hrtimer -> em485_handle_stop_tx -> get uart port spinlock CPU0 is waiting for the hrtimer callback to finish, but the hrtimer callback running on CPU1 is waiting to get the uart port spinlock. This deadlock can be avoided by not canceling the hrtimers in these paths. Setting active_timer=NULL can be done without accessing hrtimer, and that will effectively cancel operations that would otherwise have been performed by the hrtimer callback. Signed-off-by: Tomas Melin <tomas.melin@vaisala.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/tty/serial/8250/8250_port.c3
1 files changed, 0 insertions, 3 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 9880a50d664f..25e8ccd6865a 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1527,7 +1527,6 @@ static inline void __stop_tx(struct uart_8250_port *p)
return;
em485->active_timer = NULL;
- hrtimer_cancel(&em485->start_tx_timer);
__stop_tx_rs485(p);
}
@@ -1591,8 +1590,6 @@ static inline void start_tx_rs485(struct uart_port *port)
serial8250_stop_rx(&up->port);
em485->active_timer = NULL;
- if (hrtimer_is_queued(&em485->stop_tx_timer))
- hrtimer_cancel(&em485->stop_tx_timer);
mcr = serial8250_in_MCR(up);
if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) !=