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 <cchiluve@codeaurora.org>
This commit is contained in:
Chandana Kishori Chiluveru 2020-07-03 13:42:51 +05:30 • committed by Akash Asthana
commit 346e464ccf

View file

@ -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);