Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b186e7f authored by Chandana Kishori Chiluveru's avatar Chandana Kishori Chiluveru Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
parent a2839ca3
Loading
Loading
Loading
Loading
+30 −16
Original line number Diff line number Diff line
@@ -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,
							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 @@ static int stop_rx_sequencer(struct uart_port *uport)
		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)