aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
authorChanho Min <chanho0207@gmail.com>2012-02-19 20:24:40 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-24 16:50:47 -0500
commit6dc01aa65306fe46b7ba38db51fad4ed81c23d00 (patch)
treecad255d51a09c900062d9dbd2db07432dc4b5b19 /drivers/tty/serial/amba-pl011.c
parentb26469a8b139fba11d9336c1c117fafccfa9c7d5 (diff)
amba-pl011​/dma: Add check for the residue in DMA callback
In DMA-operated uart, I found that rx data can be taken by the UART interrupts during the DMA irq handler. pl011_int is occurred just before it goes inside spin_lock_irq. When it returns to the callback, DMA buffer already has been flushed. Then, pl011_dma_rx_chars gets invalid data. So I add check for the residue as the patch bellow. Signed-off-by: Chanho Min <chanho.min@lge.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r--drivers/tty/serial/amba-pl011.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6800f5f2624..cc3ea066c43 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -827,7 +827,12 @@ static void pl011_dma_rx_callback(void *data)
827{ 827{
828 struct uart_amba_port *uap = data; 828 struct uart_amba_port *uap = data;
829 struct pl011_dmarx_data *dmarx = &uap->dmarx; 829 struct pl011_dmarx_data *dmarx = &uap->dmarx;
830 struct dma_chan *rxchan = dmarx->chan;
830 bool lastbuf = dmarx->use_buf_b; 831 bool lastbuf = dmarx->use_buf_b;
832 struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ?
833 &dmarx->sgbuf_b : &dmarx->sgbuf_a;
834 size_t pending;
835 struct dma_tx_state state;
831 int ret; 836 int ret;
832 837
833 /* 838 /*
@@ -838,11 +843,21 @@ static void pl011_dma_rx_callback(void *data)
838 * we immediately trigger the next DMA job. 843 * we immediately trigger the next DMA job.
839 */ 844 */
840 spin_lock_irq(&uap->port.lock); 845 spin_lock_irq(&uap->port.lock);
846 /*
847 * Rx data can be taken by the UART interrupts during
848 * the DMA irq handler. So we check the residue here.
849 */
850 rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
851 pending = sgbuf->sg.length - state.residue;
852 BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
853 /* Then we terminate the transfer - we now know our residue */
854 dmaengine_terminate_all(rxchan);
855
841 uap->dmarx.running = false; 856 uap->dmarx.running = false;
842 dmarx->use_buf_b = !lastbuf; 857 dmarx->use_buf_b = !lastbuf;
843 ret = pl011_dma_rx_trigger_dma(uap); 858 ret = pl011_dma_rx_trigger_dma(uap);
844 859
845 pl011_dma_rx_chars(uap, PL011_DMA_BUFFER_SIZE, lastbuf, false); 860 pl011_dma_rx_chars(uap, pending, lastbuf, false);
846 spin_unlock_irq(&uap->port.lock); 861 spin_unlock_irq(&uap->port.lock);
847 /* 862 /*
848 * Do this check after we picked the DMA chars so we don't 863 * Do this check after we picked the DMA chars so we don't