From 351ea50df545a4acaf8f61784949ceedbe923f03 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Jul 2017 13:48:58 +0200 Subject: Revert "serial: imx-serial - move DMA buffer configuration to DT" This reverts commit a3015affdf76ef279fbbb3710a220bab7e9ea04b as there are complaints that it is incorrect. Reported-by: Uwe Kleine-König Cc: Nandor Han Cc: Romain Perier Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/imx.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'drivers/tty/serial/imx.c') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9e3162bf3bd1..e33da75ceac5 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -186,11 +186,6 @@ #define UART_NR 8 -/* RX DMA buffer periods */ -#define RX_DMA_PERIODS 4 -#define RX_BUF_SIZE (PAGE_SIZE) - - /* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */ enum imx_uart_type { IMX1_UART, @@ -226,7 +221,6 @@ struct imx_port { struct dma_chan *dma_chan_rx, *dma_chan_tx; struct scatterlist rx_sgl, tx_sgl[2]; void *rx_buf; - unsigned int rx_buf_size; struct circ_buf rx_ring; unsigned int rx_periods; dma_cookie_t rx_cookie; @@ -967,6 +961,8 @@ static void imx_timeout(unsigned long data) } } +#define RX_BUF_SIZE (PAGE_SIZE) + /* * There are two kinds of RX DMA interrupts(such as in the MX6Q): * [1] the RX DMA buffer is full. @@ -1049,6 +1045,9 @@ static void dma_rx_callback(void *data) } } +/* RX DMA buffer periods */ +#define RX_DMA_PERIODS 4 + static int start_rx_dma(struct imx_port *sport) { struct scatterlist *sgl = &sport->rx_sgl; @@ -1059,8 +1058,9 @@ static int start_rx_dma(struct imx_port *sport) sport->rx_ring.head = 0; sport->rx_ring.tail = 0; + sport->rx_periods = RX_DMA_PERIODS; - sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size); + sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE); if (ret == 0) { dev_err(dev, "DMA mapping error for RX.\n"); @@ -1171,7 +1171,7 @@ static int imx_uart_dma_init(struct imx_port *sport) goto err; } - sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL); + sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!sport->rx_buf) { ret = -ENOMEM; goto err; @@ -2036,7 +2036,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, { struct device_node *np = pdev->dev.of_node; int ret; - u32 dma_buf_size[2]; sport->devdata = of_device_get_match_data(&pdev->dev); if (!sport->devdata) @@ -2060,14 +2059,6 @@ static int serial_imx_probe_dt(struct imx_port *sport, if (of_get_property(np, "rts-gpios", NULL)) sport->have_rtsgpio = 1; - if (!of_property_read_u32_array(np, "fsl,dma-size", dma_buf_size, 2)) { - sport->rx_buf_size = dma_buf_size[0] * dma_buf_size[1]; - sport->rx_periods = dma_buf_size[1]; - } else { - sport->rx_buf_size = RX_BUF_SIZE; - sport->rx_periods = RX_DMA_PERIODS; - } - return 0; } #else -- cgit v1.2.3-55-g7522 From 514ab34dbad6c6fa824a1f56984c196e59082346 Mon Sep 17 00:00:00 2001 From: Ian Jamison Date: Fri, 14 Jul 2017 17:31:57 +0100 Subject: serial: imx: Prevent TX buffer PIO write when a DMA has been started Function imx_transmit_buffer starts a TX DMA if DMA is enabled, since commit 91a1a909f921 ("serial: imx: Support sw flow control in DMA mode"). It also carries on and attempts to write the same TX buffer using PIO. This results in TX data corruption and double-incrementing xmit->tail with the knock-on effect of tail passing head and a page of garbage being sent out. This seems to be triggered mostly when using RS485 half duplex on SMP systems, but is probably not limited to just those. Tested locally on an i.MX6Q with an RS485 half duplex transceiver on UART3, and also by Clemens Gruber. Tested-by: Clemens Gruber Signed-off-by: Ian Jamison Reviewed-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial/imx.c') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e33da75ceac5..80934e7bd67f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -458,7 +458,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport) } } - while (!uart_circ_empty(xmit) && + while (!uart_circ_empty(xmit) && !sport->dma_is_txing && !(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ -- cgit v1.2.3-55-g7522