Merge tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / tty / serial / 8250 / 8250_dma.c
index 148ffe4..fcd7ac6 100644 (file)
@@ -21,6 +21,7 @@ static void __dma_tx_complete(void *param)
        struct uart_8250_dma    *dma = p->dma;
        struct circ_buf         *xmit = &p->port.state->xmit;
        unsigned long   flags;
+       int             ret;
 
        dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
                                UART_XMIT_SIZE, DMA_TO_DEVICE);
@@ -36,8 +37,11 @@ static void __dma_tx_complete(void *param)
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&p->port);
 
-       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
-               serial8250_tx_dma(p);
+       ret = serial8250_tx_dma(p);
+       if (ret) {
+               p->ier |= UART_IER_THRI;
+               serial_port_out(&p->port, UART_IER, p->ier);
+       }
 
        spin_unlock_irqrestore(&p->port.lock, flags);
 }
@@ -53,6 +57,7 @@ static void __dma_rx_complete(void *param)
        dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
                                dma->rx_size, DMA_FROM_DEVICE);
 
+       dma->rx_running = 0;
        dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
        dmaengine_terminate_all(dma->rxchan);
 
@@ -69,6 +74,7 @@ int serial8250_tx_dma(struct uart_8250_port *p)
        struct uart_8250_dma            *dma = p->dma;
        struct circ_buf                 *xmit = &p->port.state->xmit;
        struct dma_async_tx_descriptor  *desc;
+       int ret;
 
        if (uart_tx_stopped(&p->port) || dma->tx_running ||
            uart_circ_empty(xmit))
@@ -80,11 +86,12 @@ int serial8250_tx_dma(struct uart_8250_port *p)
                                           dma->tx_addr + xmit->tail,
                                           dma->tx_size, DMA_MEM_TO_DEV,
                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc)
-               return -EBUSY;
+       if (!desc) {
+               ret = -EBUSY;
+               goto err;
+       }
 
        dma->tx_running = 1;
-
        desc->callback = __dma_tx_complete;
        desc->callback_param = p;
 
@@ -94,19 +101,23 @@ int serial8250_tx_dma(struct uart_8250_port *p)
                                   UART_XMIT_SIZE, DMA_TO_DEVICE);
 
        dma_async_issue_pending(dma->txchan);
-
+       if (dma->tx_err) {
+               dma->tx_err = 0;
+               if (p->ier & UART_IER_THRI) {
+                       p->ier &= ~UART_IER_THRI;
+                       serial_out(p, UART_IER, p->ier);
+               }
+       }
        return 0;
+err:
+       dma->tx_err = 1;
+       return ret;
 }
-EXPORT_SYMBOL_GPL(serial8250_tx_dma);
 
 int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 {
        struct uart_8250_dma            *dma = p->dma;
        struct dma_async_tx_descriptor  *desc;
-       struct dma_tx_state             state;
-       int                             dma_status;
-
-       dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
 
        switch (iir & 0x3f) {
        case UART_IIR_RLSI:
@@ -117,7 +128,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
                 * 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) {
+               if (dma->rx_running) {
                        dmaengine_pause(dma->rxchan);
                        __dma_rx_complete(p);
                }
@@ -126,7 +137,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
                break;
        }
 
-       if (dma_status)
+       if (dma->rx_running)
                return 0;
 
        desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
@@ -135,6 +146,7 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
        if (!desc)
                return -EBUSY;
 
+       dma->rx_running = 1;
        desc->callback = __dma_rx_complete;
        desc->callback_param = p;
 
@@ -147,7 +159,6 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(serial8250_rx_dma);
 
 int serial8250_request_dma(struct uart_8250_port *p)
 {