summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/8250/8250_dma.c11
-rw-r--r--drivers/tty/serial/8250/8250_port.c4
-rw-r--r--drivers/tty/serial/serial_core.c14
-rw-r--r--include/linux/serial_core.h2
4 files changed, 27 insertions, 4 deletions
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 890fa7ddaa7f..b3c3f7e5851a 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -64,10 +64,19 @@ 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;
+ struct uart_port *up = &p->port;
int ret;
- if (dma->tx_running)
+ if (dma->tx_running) {
+ if (up->x_char) {
+ dmaengine_pause(dma->txchan);
+ uart_xchar_out(up, UART_TX);
+ dmaengine_resume(dma->txchan);
+ }
return 0;
+ } else if (up->x_char) {
+ uart_xchar_out(up, UART_TX);
+ }
if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
/* We have been called from __dma_tx_complete() */
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 868ccb3e16cf..723ec0806799 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1819,9 +1819,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
int count;
if (port->x_char) {
- serial_out(up, UART_TX, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
+ uart_xchar_out(port, UART_TX);
return;
}
if (uart_tx_stopped(port)) {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index dc6129ddef85..eb15423f935a 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -653,6 +653,20 @@ static void uart_flush_buffer(struct tty_struct *tty)
}
/*
+ * This function performs low-level write of high-priority XON/XOFF
+ * character and accounting for it.
+ *
+ * Requires uart_port to implement .serial_out().
+ */
+void uart_xchar_out(struct uart_port *uport, int offset)
+{
+ serial_port_out(uport, offset, uport->x_char);
+ uport->icount.tx++;
+ uport->x_char = 0;
+}
+EXPORT_SYMBOL_GPL(uart_xchar_out);
+
+/*
* This function is used to send a high-priority XON/XOFF character to
* the device
*/
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c58cc142d23f..8c32935e1059 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -458,6 +458,8 @@ extern void uart_handle_cts_change(struct uart_port *uport,
extern void uart_insert_char(struct uart_port *port, unsigned int status,
unsigned int overrun, unsigned int ch, unsigned int flag);
+void uart_xchar_out(struct uart_port *uport, int offset);
+
#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
#define SYSRQ_TIMEOUT (HZ * 5)