From 41d98b5da92f8b7bd11885e7c4797197b5f3e2c3 Mon Sep 17 00:00:00 2001 From: Nandor Han Date: Mon, 8 Aug 2016 15:38:28 +0300 Subject: [PATCH] serial: imx-serial - update RX error counters when DMA is used Update error counters when DMA is used for receiving data. Do this by using DMA transaction error event instead error interrupts to reduce interrupt load. Tested-by: Peter Senna Tschudin Acked-by: Peter Senna Tschudin Signed-off-by: Nandor Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 1912136f7257..08ccfe17640d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -704,6 +704,7 @@ out: return IRQ_HANDLED; } +static void clear_rx_errors(struct imx_port *sport); static int start_rx_dma(struct imx_port *sport); /* * If the RXFIFO is filled with some data, and then we @@ -729,6 +730,11 @@ static void imx_dma_rxint(struct imx_port *sport) temp &= ~(UCR2_ATEN); writel(temp, sport->port.membase + UCR2); + /* disable the rx errors interrupts */ + temp = readl(sport->port.membase + UCR4); + temp &= ~UCR4_OREN; + writel(temp, sport->port.membase + UCR4); + /* tell the DMA to receive the data. */ start_rx_dma(sport); } @@ -961,6 +967,7 @@ static void dma_rx_callback(void *data) if (status == DMA_ERROR) { dev_err(sport->port.dev, "DMA transaction error.\n"); + clear_rx_errors(sport); return; } @@ -1057,6 +1064,31 @@ static int start_rx_dma(struct imx_port *sport) return 0; } +static void clear_rx_errors(struct imx_port *sport) +{ + unsigned int status_usr1, status_usr2; + + status_usr1 = readl(sport->port.membase + USR1); + status_usr2 = readl(sport->port.membase + USR2); + + if (status_usr2 & USR2_BRCD) { + sport->port.icount.brk++; + writel(USR2_BRCD, sport->port.membase + USR2); + } else if (status_usr1 & USR1_FRAMERR) { + sport->port.icount.frame++; + writel(USR1_FRAMERR, sport->port.membase + USR1); + } else if (status_usr1 & USR1_PARITYERR) { + sport->port.icount.parity++; + writel(USR1_PARITYERR, sport->port.membase + USR1); + } + + if (status_usr2 & USR2_ORE) { + sport->port.icount.overrun++; + writel(USR2_ORE, sport->port.membase + USR2); + } + +} + #define TXTL_DEFAULT 2 /* reset default */ #define RXTL_DEFAULT 1 /* reset default */ #define TXTL_DMA 8 /* DMA burst setting */