diff options
author | Colin Cross <ccross@android.com> | 2010-11-04 18:17:50 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2010-11-04 18:17:50 -0700 |
commit | ddbaf4bf9cab28f12e983bf794dddabffda7e357 (patch) | |
tree | 29008d68e9fb42a2e3e4559474c405139aeed738 /drivers/serial | |
parent | 3bd5b681a00bd2640c0ddb18e060519abac0d37c (diff) | |
parent | 1b26bfc7ad7810c499b8b6d64e9a8293aa46b8d1 (diff) |
Merge branch 'linux-tegra-2.6.36' into android-tegra-2.6.36
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/tegra_hsuart.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c index 785cfb229779..292863ccaaa0 100644 --- a/drivers/serial/tegra_hsuart.c +++ b/drivers/serial/tegra_hsuart.c @@ -416,13 +416,9 @@ static void tegra_tx_dma_complete_work(struct work_struct *work) struct tegra_uart_port *t = container_of(work, struct tegra_uart_port, tx_work); struct tegra_dma_req *req = &t->tx_dma_req; - struct circ_buf *xmit = &t->uport.state->xmit; - int count = req->bytes_transferred; unsigned long flags; int timeout = 20; - dev_vdbg(t->uport.dev, "%s: %d\n", __func__, count); - while ((uart_readb(t, UART_LSR) & TX_EMPTY_STATUS) != TX_EMPTY_STATUS) { timeout--; if (timeout == 0) { @@ -434,11 +430,8 @@ static void tegra_tx_dma_complete_work(struct work_struct *work) } spin_lock_irqsave(&t->uport.lock, flags); - xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); - t->tx_in_progress = 0; - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&t->uport); + t->tx_in_progress = 0; if (req->status != -TEGRA_DMA_REQ_ERROR_ABORTED) tegra_start_next_tx(t); @@ -449,7 +442,21 @@ static void tegra_tx_dma_complete_work(struct work_struct *work) static void tegra_tx_dma_complete_callback(struct tegra_dma_req *req) { struct tegra_uart_port *t = req->dev; + struct circ_buf *xmit = &t->uport.state->xmit; + int count = req->bytes_transferred; + unsigned long flags; + + dev_vdbg(t->uport.dev, "%s: %d\n", __func__, count); + + spin_lock_irqsave(&t->uport.lock, flags); + xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&t->uport); + schedule_work(&t->tx_work); + + spin_unlock_irqrestore(&t->uport.lock, flags); } static irqreturn_t tegra_uart_isr(int irq, void *data) @@ -552,6 +559,9 @@ static void tegra_stop_rx(struct uart_port *u) static void tegra_uart_hw_deinit(struct tegra_uart_port *t) { unsigned char fcr; + unsigned long flags; + + flush_work(&t->tx_work); /* Disable interrupts */ uart_writeb(t, 0, UART_IER); @@ -559,6 +569,8 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) while ((uart_readb(t, UART_LSR) & UART_LSR_TEMT) != UART_LSR_TEMT); udelay(200); + spin_lock_irqsave(&t->uport.lock, flags); + /* Reset the Rx and Tx FIFOs */ fcr = t->fcr_shadow; fcr |= UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR; @@ -568,6 +580,8 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t) clk_disable(t->clk); t->baud = 0; + + spin_unlock_irqrestore(&t->uport.lock, flags); } static void tegra_uart_free_rx_dma(struct tegra_uart_port *t) @@ -805,14 +819,11 @@ fail: static void tegra_shutdown(struct uart_port *u) { struct tegra_uart_port *t; - unsigned long flags; - spin_lock_irqsave(&u->lock, flags); t = container_of(u, struct tegra_uart_port, uport); dev_vdbg(u->dev, "+tegra_shutdown\n"); tegra_uart_hw_deinit(t); - spin_unlock_irqrestore(&u->lock, flags); t->rx_in_progress = 0; t->tx_in_progress = 0; @@ -947,11 +958,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) tegra_dma_dequeue_req(t->tx_dma, &t->tx_dma_req); - flush_work(&t->tx_work); - } - t->tx_in_progress = 0; + return; } @@ -1170,6 +1179,8 @@ static int tegra_uart_suspend(struct platform_device *pdev, pm_message_t state) u = &t->uport; uart_suspend_port(&tegra_uart_driver, u); + + flush_work(&t->tx_work); return 0; } |