From 346e464ccf6ecfc1d17592ffa946d33afa3e989d Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Fri, 3 Jul 2020 13:42:51 +0530 Subject: [PATCH] serial: msm_geni_serial: Fix DMA RX FSM reset sequence Update the DMA RX FSM reset sequence as per HPG recommendations. Currently driver calling msm_geni_serial_rx_fsm_rst() even in case of RX inactive. RX FSM reset command generates RX_RESET_DONE bit. There is a possible race between polling for RX_RESET and ISR for RX_RESET. This can result into introducing delay during BT open. Fix this by updating RX FSM reset sequence only in case of cancel command timeout. Change-Id: I90532aa72fdad462a616eded3e149bc6b721fe7b Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 38 ++++++++++------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 6985574b1350..80fdbcbb0fd9 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1384,26 +1384,6 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) start_rx_sequencer(&port->uport); } - -static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) -{ - unsigned int rx_irq_en; - int done = 0; - int tries = 0; - - rx_irq_en = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_EN); - geni_write_reg_nolog(0, uport->membase, SE_DMA_RX_IRQ_EN_SET); - geni_write_reg_nolog(1, uport->membase, SE_DMA_RX_FSM_RST); - do { - done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT, - RX_RESET_DONE, true); - tries++; - } while (!done && tries < 5); - geni_write_reg_nolog(RX_DMA_DONE | RX_RESET_DONE, uport->membase, - SE_DMA_RX_IRQ_CLR); - geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET); -} - static void msm_geni_serial_set_manual_flow(bool enable, struct msm_geni_serial_port *port) { @@ -1451,7 +1431,7 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->ipc_log_misc, "%s: RX is Inactive, geni_sts: 0x%x\n", __func__, geni_status); - goto exit_rx_seq; + return; } port->s_cmd_done = false; @@ -1510,15 +1490,25 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->console_log, "%s abort fail 0x%x\n", __func__, geni_status); } + + if (port->xfer_mode == SE_DMA) { + port->s_cmd_done = false; + reinit_completion(&port->s_cmd_timeout); + geni_write_reg_nolog(1, uport->membase, + SE_DMA_RX_FSM_RST); + + timeout = geni_wait_for_cmd_done(uport, + is_irq_masked); + if (timeout) + IPC_LOG_MSG(port->ipc_log_misc, + "%s: rx fsm reset failed\n", __func__); + } } /* Enable the interrupts once the cancel operation is done. */ msm_geni_serial_enable_interrupts(uport); port->s_cmd = false; exit_rx_seq: - if (port->xfer_mode == SE_DMA && port->rx_dma) - msm_geni_serial_rx_fsm_rst(uport); - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x\n", __func__, geni_status);