serial: msm_geni_serial: Perform Abort sequence for cancel failure

Currently driver performing Abort sequence only when we seeing timeout
for Cancel interrupt. When there is a race condition between rx data
coming into rx fifo and a cancel_s_cmd is given. The rx data will end
up consuming the rx dma buffer mapped for cancel command and due to
this geni secondary sequencer will be in active state even after
cancel command.

This changes is to check for geni status after cancel operation. If geni
is active perform abort sequence.

Change-Id: I1b463284b48eb940de342da6df9233157d48f469
Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
This commit is contained in:
Chandana Kishori Chiluveru 2020-12-16 13:29:21 +05:30 • committed by Gerrit - the friendly Code Review server
commit 2b186e7ffc

View file

@ -104,6 +104,7 @@
#define STALE_TIMEOUT (16)
#define STALE_COUNT (DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT)
#define SEC_TO_USEC (1000000)
#define SYSTEM_DELAY (500)
#define DEFAULT_BITS_PER_CHAR (10)
#define GENI_UART_NR_PORTS (6)
#define GENI_UART_CONS_PORTS (1)
@ -1437,10 +1438,11 @@ static int stop_rx_sequencer(struct uart_port *uport)
* Wait for the stale timeout to happen if there
* is any data pending in the rx fifo.
* Have a safety factor of 2 to include the interrupt
* and system latencies.
* and system latencies, add 500usec delay for interrupt
* latency or system delay.
*/
stale_delay = (STALE_COUNT * SEC_TO_USEC) / port->cur_baud;
stale_delay = (2 * stale_delay);
stale_delay = (2 * stale_delay) + SYSTEM_DELAY;
udelay(stale_delay);
}
@ -1464,22 +1466,26 @@ static int stop_rx_sequencer(struct uart_port *uport)
*/
mb();
timeout = geni_wait_for_cmd_done(uport, is_irq_masked);
if (timeout) {
geni_status = geni_read_reg_nolog(uport->membase,
geni_status = geni_read_reg_nolog(uport->membase,
SE_GENI_STATUS);
is_rx_active = geni_status & S_GENI_CMD_ACTIVE;
IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x, dma_dbg:0x%x\n", __func__,
geni_status, geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0));
if (timeout || is_rx_active) {
IPC_LOG_MSG(port->ipc_log_misc,
"%s cancel failed timeout:%d is_rx_active:%d 0x%x\n",
__func__, timeout, is_rx_active, geni_status);
IPC_LOG_MSG(port->console_log,
"%s cancel failed timeout:%d is_rx_active:%d 0x%x\n",
__func__, timeout, is_rx_active, geni_status);
geni_se_dump_dbg_regs(&port->serial_rsc,
uport->membase, port->ipc_log_misc);
/*
* Possible that stop_rx is called from system resume context
* for console usecase. In early resume, irq remains disabled
* in the system. call msm_geni_serial_handle_isr to clear
* the interrupts.
*/
is_rx_active = geni_status & S_GENI_CMD_ACTIVE;
IPC_LOG_MSG(port->ipc_log_misc,
"%s cancel failed is_rx_active:%d 0x%x\n",
__func__, is_rx_active, geni_status);
IPC_LOG_MSG(port->console_log,
"%s cancel failed is_rx_active:%d 0x%x\n",
__func__, is_rx_active, geni_status);
if (uart_console(uport) && !is_rx_active) {
msm_geni_serial_handle_isr(uport, &flags, true);
goto exit_rx_seq;
@ -1491,13 +1497,20 @@ static int stop_rx_sequencer(struct uart_port *uport)
mb();
timeout = geni_wait_for_cmd_done(uport, is_irq_masked);
if (timeout) {
geni_status = geni_read_reg_nolog(uport->membase,
SE_GENI_STATUS);
is_rx_active = geni_status & S_GENI_CMD_ACTIVE;
if (timeout || is_rx_active) {
geni_status = geni_read_reg_nolog(uport->membase,
SE_GENI_STATUS);
IPC_LOG_MSG(port->ipc_log_misc,
"%s abort fail 0x%x\n", __func__, geni_status);
"%s abort fail timeout:%d is_rx_active:%d 0x%x\n",
__func__, timeout, is_rx_active, geni_status);
IPC_LOG_MSG(port->console_log,
"%s abort fail 0x%x\n", __func__, geni_status);
"%s abort fail timeout:%d is_rx_active:%d 0x%x\n",
__func__, timeout, is_rx_active, geni_status);
geni_se_dump_dbg_regs(&port->serial_rsc,
uport->membase, port->ipc_log_misc);
}
if (port->xfer_mode == SE_DMA) {
@ -1522,8 +1535,9 @@ exit_rx_seq:
msm_geni_serial_set_manual_flow(true, port);
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);
IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x dma_dbg:0x%x\n",
__func__, geni_status,
geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0));
is_rx_active = geni_status & S_GENI_CMD_ACTIVE;
if (is_rx_active)