diff options
author | Huang Shijie <b32955@freescale.com> | 2014-05-23 12:40:40 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-28 12:41:32 -0700 |
commit | e2f2786606d49d3aae545c61c04757a64cf7e5f0 (patch) | |
tree | 6ac161033ca9b36ddaa3a87bbf3a956f967be000 /drivers/tty | |
parent | 8eccd0cd2106fbe0acc6bec3701e69e171353f25 (diff) | |
download | lwn-e2f2786606d49d3aae545c61c04757a64cf7e5f0.tar.gz lwn-e2f2786606d49d3aae545c61c04757a64cf7e5f0.zip |
serial: imx: remove the DMA wait queue
The DMA wait queue makes the code very complicated:
For RX, the @->stop_rx hook does not really stop the RX;
For TX, the @->stop_tx hook does not really stop the TX.
The above make the imx_shutdown has to wait the RX/TX DMA to be finished.
In order to make code more simple, this patch removes the DMA wait queue.
By calling the dmaengine_terminate_all, this patch makes the RX stops
immediately after we call the @->stop_rx hook, so does the TX.
Signed-off-by: Huang Shijie <b32955@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/imx.c | 42 |
1 files changed, 14 insertions, 28 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d373fe83da52..cdaeeeee6cec 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -225,7 +225,6 @@ struct imx_port { void *rx_buf; unsigned int tx_bytes; unsigned int dma_tx_nents; - wait_queue_head_t dma_wait; }; struct imx_port_ucrs { @@ -416,12 +415,10 @@ static void imx_stop_tx(struct uart_port *port) return; } - /* - * We are maybe in the SMP context, so if the DMA TX thread is running - * on other cpu, we have to wait for it to finish. - */ - if (sport->dma_is_enabled && sport->dma_is_txing) - return; + if (sport->dma_is_enabled && sport->dma_is_txing) { + dmaengine_terminate_all(sport->dma_chan_tx); + sport->dma_is_txing = 0; + } temp = readl(sport->port.membase + UCR1); writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); @@ -435,12 +432,10 @@ static void imx_stop_rx(struct uart_port *port) struct imx_port *sport = (struct imx_port *)port; unsigned long temp; - /* - * We are maybe in the SMP context, so if the DMA TX thread is running - * on other cpu, we have to wait for it to finish. - */ - if (sport->dma_is_enabled && sport->dma_is_rxing) - return; + if (sport->dma_is_enabled && sport->dma_is_rxing) { + dmaengine_terminate_all(sport->dma_chan_rx); + sport->dma_is_rxing = 0; + } temp = readl(sport->port.membase + UCR2); writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2); @@ -497,12 +492,6 @@ static void dma_tx_callback(void *data) dev_dbg(sport->port.dev, "we finish the TX DMA.\n"); uart_write_wakeup(&sport->port); - - if (waitqueue_active(&sport->dma_wait)) { - wake_up(&sport->dma_wait); - dev_dbg(sport->port.dev, "exit in %s.\n", __func__); - return; - } } static void imx_dma_tx(struct imx_port *sport) @@ -875,10 +864,6 @@ static void imx_rx_dma_done(struct imx_port *sport) writel(temp, sport->port.membase + UCR1); sport->dma_is_rxing = 0; - - /* Is the shutdown waiting for us? */ - if (waitqueue_active(&sport->dma_wait)) - wake_up(&sport->dma_wait); } /* @@ -1025,8 +1010,6 @@ static void imx_enable_dma(struct imx_port *sport) { unsigned long temp; - init_waitqueue_head(&sport->dma_wait); - /* set UCR1 */ temp = readl(sport->port.membase + UCR1); temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN | @@ -1218,10 +1201,13 @@ static void imx_shutdown(struct uart_port *port) unsigned long flags; if (sport->dma_is_enabled) { - /* We have to wait for the DMA to finish. */ - wait_event(sport->dma_wait, - !sport->dma_is_rxing && !sport->dma_is_txing); + /* + * The upper layer may does not call the @->stop_tx and + * @->stop_rx, so we call them ourselves. + */ + imx_stop_tx(port); imx_stop_rx(port); + imx_disable_dma(sport); imx_uart_dma_exit(sport); } |