Skip to content

Commit

Permalink
serial: tegra: Correct shutdown of UARTs
Browse files Browse the repository at this point in the history
There are two issues in the shutdown path of the UARTs which are:
1. The function tegra_uart_shutdown() calls tegra_uart_flush_buffer()
   to stop DMA TX transfers. However, tegra_uart_flush_buffer() is
   called after the DMA channels have already been freed and so actually
   does nothing.
2. The function that frees the DMA channels
   (tegra_uart_dma_channel_free()), unmaps the dma buffer before
   freeing the DMA channel and does not ensure the DMA has been
   stopped.

Resolve this by fixing the code in tegra_uart_dma_channel_free() to
ensure the DMA is stopped, free the DMA channel and then unmap the DMA
buffer. Finally, remove the unnecessary call to tegra_uart_flush_buffer().

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jon Hunter authored and Greg Kroah-Hartman committed May 10, 2015
1 parent 49433c8 commit d92aca3
Showing 1 changed file with 4 additions and 7 deletions.
11 changes: 4 additions & 7 deletions drivers/tty/serial/serial-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,24 +1020,23 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup,
static void tegra_uart_dma_channel_free(struct tegra_uart_port *tup,
bool dma_to_memory)
{
struct dma_chan *dma_chan;

if (dma_to_memory) {
dmaengine_terminate_all(tup->rx_dma_chan);
dma_release_channel(tup->rx_dma_chan);
dma_free_coherent(tup->uport.dev, TEGRA_UART_RX_DMA_BUFFER_SIZE,
tup->rx_dma_buf_virt, tup->rx_dma_buf_phys);
dma_chan = tup->rx_dma_chan;
tup->rx_dma_chan = NULL;
tup->rx_dma_buf_phys = 0;
tup->rx_dma_buf_virt = NULL;
} else {
dmaengine_terminate_all(tup->tx_dma_chan);
dma_release_channel(tup->tx_dma_chan);
dma_unmap_single(tup->uport.dev, tup->tx_dma_buf_phys,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_chan = tup->tx_dma_chan;
tup->tx_dma_chan = NULL;
tup->tx_dma_buf_phys = 0;
tup->tx_dma_buf_virt = NULL;
}
dma_release_channel(dma_chan);
}

static int tegra_uart_startup(struct uart_port *u)
Expand Down Expand Up @@ -1104,8 +1103,6 @@ static void tegra_uart_shutdown(struct uart_port *u)
tegra_uart_dma_channel_free(tup, true);
tegra_uart_dma_channel_free(tup, false);
free_irq(u->irq, tup);

tegra_uart_flush_buffer(u);
}

static void tegra_uart_enable_ms(struct uart_port *u)
Expand Down

0 comments on commit d92aca3

Please sign in to comment.