Revert "serial: imx: remove the DMA wait queue"

This reverts commit e2f2786606.

Huang reports that this patch is broken and should be reverted.

Cc: Huang Shijie <b32955@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2014-05-29 19:30:54 -07:00
parent bd71a1c088
commit 9ce4f8f3f4
1 changed files with 28 additions and 14 deletions

View File

@ -225,6 +225,7 @@ struct imx_port {
void *rx_buf; void *rx_buf;
unsigned int tx_bytes; unsigned int tx_bytes;
unsigned int dma_tx_nents; unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
}; };
struct imx_port_ucrs { struct imx_port_ucrs {
@ -415,10 +416,12 @@ static void imx_stop_tx(struct uart_port *port)
return; return;
} }
if (sport->dma_is_enabled && sport->dma_is_txing) { /*
dmaengine_terminate_all(sport->dma_chan_tx); * We are maybe in the SMP context, so if the DMA TX thread is running
sport->dma_is_txing = 0; * on other cpu, we have to wait for it to finish.
} */
if (sport->dma_is_enabled && sport->dma_is_txing)
return;
temp = readl(sport->port.membase + UCR1); temp = readl(sport->port.membase + UCR1);
writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
@ -432,10 +435,12 @@ static void imx_stop_rx(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
unsigned long temp; unsigned long temp;
if (sport->dma_is_enabled && sport->dma_is_rxing) { /*
dmaengine_terminate_all(sport->dma_chan_rx); * We are maybe in the SMP context, so if the DMA TX thread is running
sport->dma_is_rxing = 0; * on other cpu, we have to wait for it to finish.
} */
if (sport->dma_is_enabled && sport->dma_is_rxing)
return;
temp = readl(sport->port.membase + UCR2); temp = readl(sport->port.membase + UCR2);
writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2); writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
@ -496,6 +501,12 @@ static void dma_tx_callback(void *data)
dev_dbg(sport->port.dev, "we finish the TX DMA.\n"); dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
uart_write_wakeup(&sport->port); 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) static void imx_dma_tx(struct imx_port *sport)
@ -868,6 +879,10 @@ static void imx_rx_dma_done(struct imx_port *sport)
writel(temp, sport->port.membase + UCR1); writel(temp, sport->port.membase + UCR1);
sport->dma_is_rxing = 0; sport->dma_is_rxing = 0;
/* Is the shutdown waiting for us? */
if (waitqueue_active(&sport->dma_wait))
wake_up(&sport->dma_wait);
} }
/* /*
@ -1014,6 +1029,8 @@ static void imx_enable_dma(struct imx_port *sport)
{ {
unsigned long temp; unsigned long temp;
init_waitqueue_head(&sport->dma_wait);
/* set UCR1 */ /* set UCR1 */
temp = readl(sport->port.membase + UCR1); temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN | temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
@ -1205,13 +1222,10 @@ static void imx_shutdown(struct uart_port *port)
unsigned long flags; unsigned long flags;
if (sport->dma_is_enabled) { if (sport->dma_is_enabled) {
/* /* We have to wait for the DMA to finish. */
* The upper layer may does not call the @->stop_tx and wait_event(sport->dma_wait,
* @->stop_rx, so we call them ourselves. !sport->dma_is_rxing && !sport->dma_is_txing);
*/
imx_stop_tx(port);
imx_stop_rx(port); imx_stop_rx(port);
imx_disable_dma(sport); imx_disable_dma(sport);
imx_uart_dma_exit(sport); imx_uart_dma_exit(sport);
} }