diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2010-09-06 18:07:47 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2010-09-16 04:03:17 -0700 |
commit | 94469e8891c5a00c2f298c8d9c016857d948e694 (patch) | |
tree | f9db558a76c48695e91b0de351e7d0829f5be528 /drivers | |
parent | 95a256fdaa601b17ae13d4749cf846acc389fd75 (diff) |
[arm/tegra] dma and serial: Adding pointer checks
Adding the valid pointer checks before accessing the pointers
which is passed when public apis are called.
Also resetting the pointers to null once the allocated handles
are freed.
(cherry picked from commit 0954407534a757b316bc35a0232968feed23243a)
Change-Id: Ib8b99f0556fb9a98c74ba8911a00879451fad9e5
Reviewed-on: http://git-master/r/6578
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/serial/tegra_hsuart.c | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c index 353a43bc3906..3cffbf0a1dfe 100755 --- a/drivers/serial/tegra_hsuart.c +++ b/drivers/serial/tegra_hsuart.c @@ -44,6 +44,7 @@ #include <mach/dma.h> #include <mach/pinmux.h> #include <mach/serial.h> +#include <mach/clk.h> #include "nvodm_uart.h" #define TX_EMPTY_STATUS (UART_LSR_TEMT | UART_LSR_THRE) @@ -653,7 +654,7 @@ static void tegra_stop_rx(struct uart_port *u) t->rx_in_progress = 0; } - if (t->rx_dma) { + if ((t->use_rx_dma) && !IS_ERR_OR_NULL(t->rx_dma)) { tegra_dma_dequeue(t->rx_dma); tty_flip_buffer_push(u->state->port.tty); } @@ -676,7 +677,7 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) fcr |= UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR; uart_writeb(t, fcr, UART_FCR); - udelay(2000); + udelay(200); clk_disable(t->clk); t->baud = 0; @@ -691,10 +692,13 @@ static void tegra_uart_free_rx_dma(struct tegra_uart_port *t) return; tegra_dma_free_channel(t->rx_dma); + t->rx_dma = NULL; if (likely(t->rx_dma_req.dest_addr)) dma_free_coherent(t->uport.dev, t->rx_dma_req.size, t->rx_dma_req.virt_addr, t->rx_dma_req.dest_addr); + t->rx_dma_req.dest_addr = 0; + t->rx_dma_req.virt_addr = NULL; t->use_rx_dma = false; } @@ -716,7 +720,12 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t) tegra_pinmux_config_tristate_table(t->pinmux, t->nr_pins, TEGRA_TRI_NORMAL); clk_enable(t->clk); - msleep(10); + + /* Reset the UART controller to clear all previous status.*/ + tegra_periph_reset_assert(t->clk); + udelay(100); + tegra_periph_reset_deassert(t->clk); + udelay(100); t->rx_in_progress = 0; @@ -820,12 +829,11 @@ static int tegra_uart_init_rx_dma(struct tegra_uart_port *t) dma_addr_t rx_dma_phys; void *rx_dma_virt; + memset(&t->rx_dma_req, 0, sizeof(t->rx_dma_req)); t->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_CONTINUOUS); if (IS_ERR_OR_NULL(t->rx_dma)) return -ENODEV; - memset(&t->rx_dma_req, 0, sizeof(t->rx_dma_req)); - t->rx_dma_req.size = UART_RX_DMA_BUFFER_SIZE; rx_dma_virt = dma_alloc_coherent(t->uport.dev, t->rx_dma_req.size, &rx_dma_phys, GFP_KERNEL); @@ -863,29 +871,32 @@ static int tegra_startup(struct uart_port *u) t = container_of(u, struct tegra_uart_port, uport); sprintf(t->port_name, "tegra_uart_%d", u->line); + memset(&t->tx_dma_req, 0, sizeof(t->tx_dma_req)); t->use_tx_dma = false; if (!TX_FORCE_PIO) { t->tx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); if (!IS_ERR_OR_NULL(t->tx_dma)) t->use_tx_dma = true; - } - if (t->use_tx_dma) { - t->tx_dma_req.instance = u->line; - t->tx_dma_req.complete = tegra_tx_dma_complete_callback; - t->tx_dma_req.to_memory = 0; - - t->tx_dma_req.dest_addr = (unsigned long)t->uport.mapbase; - t->tx_dma_req.dest_wrap = 4; - t->tx_dma_req.source_wrap = 0; - t->tx_dma_req.source_bus_width = 32; - t->tx_dma_req.dest_bus_width = 8; - t->tx_dma_req.req_sel = dma_req_sel[t->uport.line]; - t->tx_dma_req.dev = t; - t->tx_dma_req.size = 0; - t->tx_dma_req.is_repeat_req = false; - t->xmit_dma_addr = dma_map_single(t->uport.dev, - t->uport.state->xmit.buf, UART_XMIT_SIZE, - DMA_TO_DEVICE); + if (t->use_tx_dma) { + t->tx_dma_req.instance = u->line; + t->tx_dma_req.complete = tegra_tx_dma_complete_callback; + t->tx_dma_req.to_memory = 0; + + t->tx_dma_req.dest_addr = + (unsigned long)t->uport.mapbase; + t->tx_dma_req.dest_wrap = 4; + t->tx_dma_req.source_wrap = 0; + t->tx_dma_req.source_bus_width = 32; + t->tx_dma_req.dest_bus_width = 8; + t->tx_dma_req.req_sel = dma_req_sel[t->uport.line]; + t->tx_dma_req.dev = t; + t->tx_dma_req.size = 0; + t->tx_dma_req.is_repeat_req = false; + t->xmit_dma_addr = dma_map_single(t->uport.dev, + t->uport.state->xmit.buf, + UART_XMIT_SIZE, + DMA_TO_DEVICE); + } } t->tx_in_progress = 0; @@ -928,12 +939,18 @@ static void tegra_shutdown(struct uart_port *u) tegra_uart_hw_deinit(t); spin_unlock_irqrestore(&u->lock, flags); + t->rx_in_progress = 0; + t->tx_in_progress = 0; + tegra_uart_free_rx_dma(t); - if (t->use_tx_dma) + if (t->use_tx_dma) { tegra_dma_free_channel(t->tx_dma); + t->tx_dma = NULL; + dma_unmap_single(t->uport.dev, t->xmit_dma_addr, UART_XMIT_SIZE, + DMA_TO_DEVICE); + t->xmit_dma_addr = 0; + } - dma_unmap_single(t->uport.dev, t->xmit_dma_addr, UART_XMIT_SIZE, - DMA_TO_DEVICE); free_irq(u->irq, t); dev_vdbg(u->dev, "-tegra_shutdown\n"); } @@ -1059,8 +1076,9 @@ static void tegra_stop_tx(struct uart_port *u) t = container_of(u, struct tegra_uart_port, uport); - if (t->use_tx_dma) + if ((t->use_tx_dma) && !IS_ERR_OR_NULL(t->tx_dma)) tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req); + t->tx_in_progress = 0; return; } @@ -1219,7 +1237,7 @@ static void tegra_flush_buffer(struct uart_port *u) t = container_of(u, struct tegra_uart_port, uport); - if (t->use_tx_dma) { + if (t->use_tx_dma && !IS_ERR_OR_NULL(t->tx_dma)) { tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req); t->tx_dma_req.size = 0; } @@ -1325,7 +1343,6 @@ static int tegra_uart_resume(struct platform_device *pdev) if (t->uart_state == TEGRA_UART_SUSPEND) { uart_resume_port(&tegra_uart_driver, u); - t->uart_state = TEGRA_UART_OPENED; } if (t->odm_uart_handle) NvOdmUartResume(t->odm_uart_handle); @@ -1437,6 +1454,9 @@ void tegra_uart_request_clock_off(struct uart_port *uport) unsigned long flags; struct tegra_uart_port *t; + if (IS_ERR_OR_NULL(uport)) + BUG(); + dev_vdbg(uport->dev, "tegra_uart_request_clock_off"); t = container_of(uport, struct tegra_uart_port, uport); @@ -1455,6 +1475,9 @@ void tegra_uart_request_clock_on(struct uart_port *uport) unsigned long flags; struct tegra_uart_port *t; + if (IS_ERR_OR_NULL(uport)) + BUG(); + t = container_of(uport, struct tegra_uart_port, uport); spin_lock_irqsave(&uport->lock, flags); if (t->uart_state == TEGRA_UART_CLOCK_OFF) { |