diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index e9488f2d0822..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; @@ -1686,6 +1687,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 +1749,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; @@ -1926,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; @@ -1975,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) { @@ -2653,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)) @@ -2696,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) {