summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2022-04-25 17:33:59 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-26 13:28:34 +0200
commite8ffbb71f783f577b24c25bd4dd1c7119d344924 (patch)
tree2b9654e63eccf780ee364bdfc84d02f81d7a2634 /drivers/tty/serial/8250
parent31f6bd7fad3b149a1eb6f67fc2e742e4df369b3d (diff)
serial: 8250: use THRE & __stop_tx also with DMA
8250 DMA tx complete path lacks calls to normal 8250 stop handling. It does not use THRE to detect true completion of the tx and also doesn't call __stop_tx. This leads to problems with em485 that needs to handle RTS timing. Instead of handling tx stop internally within 8250 dma code, enable THRE when tx'able data runs out and tweak serial8250_handle_irq to call only __stop_tx when uart is using DMA. It also seems bit early to call serial8250_rpm_put_tx from there while tx is still underway(?). Tested-by: Vicente Bergas <vicencb@gmail.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/20220425143410.12703-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r--drivers/tty/serial/8250/8250_dma.c3
-rw-r--r--drivers/tty/serial/8250/8250_port.c9
2 files changed, 7 insertions, 5 deletions
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 1bdc8d6432fe..7133fceed35e 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -34,7 +34,7 @@ static void __dma_tx_complete(void *param)
uart_write_wakeup(&p->port);
ret = serial8250_tx_dma(p);
- if (ret)
+ if (ret || !dma->tx_running)
serial8250_set_THRI(p);
spin_unlock_irqrestore(&p->port.lock, flags);
@@ -80,7 +80,6 @@ int serial8250_tx_dma(struct uart_8250_port *p)
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
/* We have been called from __dma_tx_complete() */
- serial8250_rpm_put_tx(p);
return 0;
}
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 5bba852d30f7..40d4895fd208 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1948,9 +1948,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
- if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
- (up->ier & UART_IER_THRI))
- serial8250_tx_chars(up);
+ if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
+ if (!up->dma || up->dma->tx_err)
+ serial8250_tx_chars(up);
+ else
+ __stop_tx(up);
+ }
uart_unlock_and_check_sysrq_irqrestore(port, flags);