Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2993348AbbEEQG0 (ORCPT ); Tue, 5 May 2015 12:06:26 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:7804 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2993142AbbEEOSZ (ORCPT ); Tue, 5 May 2015 10:18:25 -0400 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Tue, 05 May 2015 07:16:59 -0700 From: Jon Hunter To: Laxman Dewangan , Greg Kroah-Hartman , Jiri Slaby CC: , , , Jon Hunter Subject: [PATCH 7/8] serial: tegra: Correct shutdown of UARTs Date: Tue, 5 May 2015 15:17:58 +0100 Message-ID: <1430835479-6613-8-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1430835479-6613-1-git-send-email-jonathanh@nvidia.com> References: <1430835479-6613-1-git-send-email-jonathanh@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2501 Lines: 69 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 --- drivers/tty/serial/serial-tegra.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 987c05665e62..96378da9aefc 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -1020,24 +1020,23 @@ scrub: 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) @@ -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) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/