From ae7aa712f456426af2c755e9e84532f48b4c71ad Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Mon, 30 Aug 2021 20:12:31 +0530 Subject: [PATCH] serial: msm_geni_serial: Fix deadlock scenario with rx_lock In one core msm_geni_serial driver acquiring port->rx_lock in stop_rx_sequencer function in process context by calling handle_rx_dma_xfer and this process is preempted becz of core interrupt is fired on same core and then same lock is trying to acquire from interrupt context. This is resulting in deadlock issue. Below are the core call stack of deadlock. Core 0 LR: _raw_spin_lock[jt]+40 [] handle_rx_dma_xfer+0x44 [] msm_geni_serial_handle_isr+0x6fc [] msm_geni_serial_isr+0x40 [] __handle_irq_event_percpu+0x158 [] handle_irq_event+0x60 [] handle_fasteoi_irq+0x128 [] __handle_domain_irq+0xa0 [] gic_handle_irq$7f58c51dd0f0d487d89dbb027abc57c5+0xb8 [] el1_irq+0x104 [] handle_rx_dma_xfer+0x50 [] stop_rx_sequencer+0x118 [] msm_geni_serial_set_termios+0x114 [] uart_change_speed+0x58 [] uart_set_termios$ecf561cdccc9a487f79dc2d4825d91c7+0xd4 [] tty_set_termios[jt]+0x1c0 [] set_termios+0x124 [] tty_mode_ioctl+0x468 [] n_tty_ioctl_helper+0xac [] n_tty_ioctl$31461d4e731178606d28313f43c714a4[jt]+0x318 [] tty_ioctl+0x37c [] do_vfs_ioctl+0x384 [] __arm64_sys_ioctl+0x78 [] el0_svc_common[jt]+0xd8 [] el0_svc_handler+0x68 [] ret_to_user[jt]+0x0. Change-Id: I7e1392cd82a93b1da6b19f05dbe67b66d46193f1 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index f81be32b396b..ed0b027b2047 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -2100,8 +2100,9 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); u32 dma_rx_status; + unsigned long lock_flags; - spin_lock(&msm_port->rx_lock); + spin_lock_irqsave(&msm_port->rx_lock, lock_flags); dma_rx_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_STAT); @@ -2166,7 +2167,7 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) ret = true; exit: - spin_unlock(&msm_port->rx_lock); + spin_unlock_irqrestore(&msm_port->rx_lock, lock_flags); return ret; }