From de89e43ada08a8409dbdadb5728bee2e1c89661a Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 10 Sep 2020 13:29:46 +0530 Subject: [PATCH 1/2] serial: msm_geni_serial: Add delay for rx invalid transfer Check for RX data in rx buffer for faulty transfer and add delay of 2 msecs delay in order for dma rx transfer to be actually completed. Also dump required qup registers when the uart dma rx data is seen as all zeros. Change-Id: Ifaa0cb7d22b8419ffacfee7212b0a28ed8ebf2a1 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index e9488f2d0822..d449d54e03cd 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1686,6 +1686,40 @@ exit_handle_tx: return 0; } +static void check_rx_buf(char *buf, struct uart_port *uport, int size) +{ + struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); + unsigned int rx_data; + bool fault = false; + + rx_data = *(u32 *)buf; + /* check for first 4 bytes of RX data for faulty zero pattern */ + if (rx_data == 0x0) { + if (size <= 4) { + fault = true; + } else { + /* + * check for last 4 bytes of data in RX buffer for + * faulty pattern + */ + if (memcmp(buf+(size-4), "\x0\x0\x0\x0", 4) == 0) + fault = true; + } + + if (fault) { + IPC_LOG_MSG(msm_port->ipc_log_rx, + "RX Invalid packet %s\n", __func__); + geni_se_dump_dbg_regs(&msm_port->serial_rsc, + uport->membase, msm_port->ipc_log_misc); + /* + * Add 2 msecs delay in order for dma rx transfer + * to be actually completed. + */ + udelay(2000); + } + } +} + static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) { struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1714,6 +1748,10 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) __func__, rx_bytes); goto exit_handle_dma_rx; } + + /* Check RX buffer data for faulty pattern*/ + check_rx_buf((char *)msm_port->rx_buf, uport, rx_bytes); + if (drop_rx) goto exit_handle_dma_rx; From 8f9bea1d7ccd7fd57a89416303836f33ef9d22e8 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 4 Jun 2020 09:12:26 +0530 Subject: [PATCH 2/2] serial: msm_geni_serial: Add new UART IPC log file in DMA mode This patch adds new IPC log file to dump IRQ registers to know the interrupt status in dma mode. This will help in debugging interrupt storm issues in dma mode. Also increase the IPC log buffer size. Change-Id: I33a32e8d237769808a9c7553c9c3e6d1024d9f50 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 37 ++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index d449d54e03cd..37dd85279f8c 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -112,9 +112,9 @@ #define WAIT_XFER_MAX_ITER (2) #define WAIT_XFER_MAX_TIMEOUT_US (10000) #define WAIT_XFER_MIN_TIMEOUT_US (9000) -#define IPC_LOG_PWR_PAGES (6) -#define IPC_LOG_MISC_PAGES (10) -#define IPC_LOG_TX_RX_PAGES (10) +#define IPC_LOG_PWR_PAGES (10) +#define IPC_LOG_MISC_PAGES (30) +#define IPC_LOG_TX_RX_PAGES (30) #define DATA_BYTES_PER_LINE (32) #define M_IRQ_BITS (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN |\ @@ -182,6 +182,7 @@ struct msm_geni_serial_port { void *ipc_log_pwr; void *ipc_log_misc; void *console_log; + void *ipc_log_irqstatus; unsigned int cur_baud; int ioctl_count; int edge_count; @@ -1964,6 +1965,8 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport, { unsigned int m_irq_status; unsigned int s_irq_status; + unsigned int dma_tx_status; + unsigned int dma_rx_status; unsigned int dma; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); struct tty_port *tport = &uport->state->port; @@ -2013,9 +2016,20 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport, s_cmd_done = handle_rx_fifo_xfer(s_irq_status, uport, flags, is_irq_masked); } else { - m_cmd_done = handle_tx_dma_xfer(m_irq_status, uport); - s_cmd_done = handle_rx_dma_xfer(s_irq_status, uport); - } + dma_tx_status = geni_read_reg_nolog(uport->membase, + SE_DMA_TX_IRQ_STAT); + dma_rx_status = geni_read_reg_nolog(uport->membase, + SE_DMA_RX_IRQ_STAT); + + if (m_irq_status || s_irq_status || + dma_tx_status || dma_rx_status) + IPC_LOG_MSG(msm_port->ipc_log_irqstatus, + "%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x\n", + __func__, s_irq_status, m_irq_status, + dma_tx_status, dma_rx_status); + m_cmd_done = handle_tx_dma_xfer(m_irq_status, uport); + s_cmd_done = handle_rx_dma_xfer(s_irq_status, uport); + } exit_geni_serial_isr: if (m_cmd_done) { @@ -2691,7 +2705,7 @@ static void console_unregister(struct uart_driver *drv) static void msm_geni_serial_debug_init(struct uart_port *uport, bool console) { struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); - char name[30]; + char name[35]; msm_port->dbg = debugfs_create_dir(dev_name(uport->dev), NULL); if (IS_ERR_OR_NULL(msm_port->dbg)) @@ -2734,6 +2748,15 @@ static void msm_geni_serial_debug_init(struct uart_port *uport, bool console) if (!msm_port->ipc_log_misc) dev_info(uport->dev, "Err in Misc IPC Log\n"); } + memset(name, 0, sizeof(name)); + if (!msm_port->ipc_log_irqstatus) { + scnprintf(name, sizeof(name), "%s%s", + dev_name(uport->dev), "_irqstatus"); + msm_port->ipc_log_irqstatus = ipc_log_context_create( + IPC_LOG_MISC_PAGES, name, 0); + if (!msm_port->ipc_log_irqstatus) + dev_info(uport->dev, "Err in irqstatus IPC Log\n"); + } } else { memset(name, 0, sizeof(name)); if (!msm_port->console_log) {