@@ -41,6 +41,7 @@ struct uart_8250_dma {
size_t tx_size;
unsigned char tx_running:1;
+ unsigned char tx_err: 1;
};
struct old_serial_port {
@@ -1594,8 +1594,10 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
- if (!up->dma && (status & UART_LSR_THRE))
+ if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+ (status & UART_LSR_THRE)) {
serial8250_tx_chars(up);
+ }
spin_unlock_irqrestore(&port->lock, flags);
return 1;
@@ -36,8 +36,16 @@ 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);
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
+ int ret;
+
+ ret = serial8250_tx_dma(p);
+ if (ret) {
+ dma->tx_err = 1;
+ p->ier |= UART_IER_THRI;
+ serial_port_out(&p->port, UART_IER, p->ier);
+ }
+ }
spin_unlock_irqrestore(&p->port.lock, flags);
}
@@ -69,6 +77,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,8 +89,10 @@ 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;
@@ -94,8 +105,17 @@ 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);