Implement a custom tx_chars() routine for Moxa MU860 UART to manage Tx
FIFO and xmit buffer handling.
The routine fetches up to fifosize bytes from the transmit FIFO and writes
them to UART_TX using serial_out(). Wakeup and stop_tx conditions are
handled based on FIFO state.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/tty/serial/8250/8250_mxupci.c | 33 ++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_mxupci.c b/drivers/tty/serial/8250/8250_mxupci.c
index ab6042f157c6..0eeaf0fa1538 100644
--- a/drivers/tty/serial/8250/8250_mxupci.c
+++ b/drivers/tty/serial/8250/8250_mxupci.c
@@ -240,6 +240,37 @@ static void mxupci8250_rx_chars(struct uart_8250_port *up)
}
}
+static void mxupci8250_tx_chars(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ struct tty_port *tport = &port->state->port;
+ unsigned int count, i;
+ unsigned char c;
+
+ if (port->x_char) {
+ uart_xchar_out(port, UART_TX);
+ return;
+ }
+ if (uart_tx_stopped(port) || kfifo_is_empty(&tport->xmit_fifo)) {
+ port->ops->stop_tx(port);
+ return;
+ }
+ count = kfifo_len(&tport->xmit_fifo);
+ count = min(count, port->fifosize);
+
+ for (i = 0; i < count; ++i) {
+ if (!uart_fifo_get(port, &c))
+ break;
+
+ serial_out(up, UART_TX, c);
+ }
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (kfifo_is_empty(&tport->xmit_fifo) && !(up->capabilities & UART_CAP_RPM))
+ port->ops->stop_tx(port);
+}
+
static int mxupci8250_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
@@ -271,7 +302,7 @@ static int mxupci8250_handle_irq(struct uart_port *port)
serial8250_modem_status(up);
if ((lsr & UART_LSR_THRE) && (up->ier & UART_IER_THRI))
- serial8250_tx_chars(up);
+ mxupci8250_tx_chars(up);
uart_unlock_and_check_sysrq_irqrestore(port, flags);
--
2.45.2