summary refs log tree commit diff
path: root/drivers/tty
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2013-04-10 16:58:25 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-11 13:18:39 -0700
commit75df022b5f8982a375adb04e9e4c0a34a9689ed9 (patch)
treee13d9f57e5207232907263a867400c033ed16d80 /drivers/tty
parent5ea5b24da80322b8136cb000a7340cdc29a3d6dc (diff)
downloadlinux-75df022b5f8982a375adb04e9e4c0a34a9689ed9.tar.gz
serial: 8250_dma: Fix RX handling
Overrun, parity and framing errors should be handled in
8250_core. This also adds check for the dma_status and exits
if the channel is not idle.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/8250/8250_dma.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index ce2518d5dfd1..66430614510a 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -101,20 +101,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 	struct dma_tx_state		state;
 	int				dma_status;
 
-	/*
-	 * If RCVR FIFO trigger level was not reached, complete the transfer and
-	 * let 8250.c copy the remaining data.
-	 */
-	if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
-		dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie,
-						&state);
+	dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+
+	switch (iir & 0x3f) {
+	case UART_IIR_RLSI:
+		/* 8250_core handles errors and break interrupts */
+		return -EIO;
+	case UART_IIR_RX_TIMEOUT:
+		/*
+		 * If RCVR FIFO trigger level was not reached, complete the
+		 * transfer and let 8250_core copy the remaining data.
+		 */
 		if (dma_status == DMA_IN_PROGRESS) {
 			dmaengine_pause(dma->rxchan);
 			__dma_rx_complete(p);
 		}
 		return -ETIMEDOUT;
+	default:
+		break;
 	}
 
+	if (dma_status)
+		return 0;
+
 	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
 					   dma->rx_size, DMA_DEV_TO_MEM,
 					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);