serial: 8250_dma: Fix RX handling
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>
Wed, 10 Apr 2013 13:58:25 +0000 (16:58 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Apr 2013 20:18:39 +0000 (13:18 -0700)
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>
drivers/tty/serial/8250/8250_dma.c

index ce2518d5dfd168ccfd6079f1a917797ce3e363c4..66430614510a09effe3079eda130b4ad8f4a52d9 100644 (file)
@@ -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);