]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tty: serial: use uart_port_tx_limited()
authorJiri Slaby (SUSE) <jirislaby@kernel.org>
Tue, 4 Oct 2022 10:49:27 +0000 (12:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Nov 2022 02:32:40 +0000 (03:32 +0100)
uart_port_tx_limited() is a new helper to send characters to the device.
Use it in these drivers.

mux.c also needs to define tx_done(). But I'm not sure if the driver
really wants to wait for all the characters to dismiss from the HW fifo
at this code point. Hence I marked this as FIXME.

Cc: Russell King <linux@armlinux.org.uk>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: bcm-kernel-feedback-list@broadcom.com
Cc: "Pali Rohár" <pali@kernel.org>
Cc: Kevin Cernekee <cernekee@gmail.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Orson Zhai <orsonzhai@gmail.com>
Cc: Baolin Wang <baolin.wang7@gmail.com>
Cc: Chunyan Zhang <zhang.lyra@gmail.com>
Cc: Patrice Chotard <patrice.chotard@foss.st.com>
Cc: linux-riscv@lists.infradead.org
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
Link: https://lore.kernel.org/r/20221004104927.14361-4-jirislaby@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
14 files changed:
drivers/tty/serial/21285.c
drivers/tty/serial/altera_jtaguart.c
drivers/tty/serial/amba-pl010.c
drivers/tty/serial/apbuart.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/mux.c
drivers/tty/serial/mvebu-uart.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pxa.c
drivers/tty/serial/rp2.c
drivers/tty/serial/serial_txx9.c
drivers/tty/serial/sifive.c
drivers/tty/serial/sprd_serial.c
drivers/tty/serial/st-asc.c

index c7d34823f7155ae253332f6d2051879c3e87c731..185462fd959c6d7bf9bb2d1fba8caa9e2535a3a9 100644 (file)
@@ -154,35 +154,13 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
 {
        struct uart_port *port = dev_id;
-       struct circ_buf *xmit = &port->state->xmit;
-       int count = 256;
-
-       if (port->x_char) {
-               *CSR_UARTDR = port->x_char;
-               port->icount.tx++;
-               port->x_char = 0;
-               goto out;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               serial21285_stop_tx(port);
-               goto out;
-       }
-
-       do {
-               *CSR_UARTDR = xmit->buf[xmit->tail];
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               serial21285_stop_tx(port);
+       uart_port_tx_limited(port, ch, 256,
+               !(*CSR_UARTFLG & 0x20),
+               *CSR_UARTDR = ch,
+               ({}));
 
- out:
        return IRQ_HANDLED;
 }
 
index c2d154d78e545904a3a6ac9c2d5ede39dda9be6e..aa49553fac5847ea03f47e52c7088fbb2969480f 100644 (file)
@@ -146,37 +146,15 @@ static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
 static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
 {
        struct uart_port *port = &pp->port;
-       struct circ_buf *xmit = &port->state->xmit;
-       unsigned int pending, count;
-
-       if (port->x_char) {
-               /* Send special char - probably flow control */
-               writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
-               port->x_char = 0;
-               port->icount.tx++;
-               return;
-       }
+       unsigned int count;
+       u8 ch;
 
-       pending = uart_circ_chars_pending(xmit);
-       if (pending > 0) {
-               count = altera_jtaguart_tx_space(port, NULL);
-               if (count > pending)
-                       count = pending;
-               if (count > 0) {
-                       pending -= count;
-                       while (count--) {
-                               writel(xmit->buf[xmit->tail],
-                                      port->membase + ALTERA_JTAGUART_DATA_REG);
-                               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-                               port->icount.tx++;
-                       }
-                       if (pending < WAKEUP_CHARS)
-                               uart_write_wakeup(port);
-               }
-       }
+       count = altera_jtaguart_tx_space(port, NULL);
 
-       if (pending == 0)
-               altera_jtaguart_stop_tx(port);
+       uart_port_tx_limited(port, ch, count,
+               true,
+               writel(ch, port->membase + ALTERA_JTAGUART_DATA_REG),
+               ({}));
 }
 
 static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
index af27fb8ec145161cb190e69c012d4da5264ac78d..a98fae2ca422d2eb05e85be85390ab5cef50cddc 100644 (file)
@@ -164,34 +164,12 @@ static void pl010_rx_chars(struct uart_port *port)
 
 static void pl010_tx_chars(struct uart_port *port)
 {
-       struct circ_buf *xmit = &port->state->xmit;
-       int count;
+       u8 ch;
 
-       if (port->x_char) {
-               writel(port->x_char, port->membase + UART01x_DR);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               pl010_stop_tx(port);
-               return;
-       }
-
-       count = port->fifosize >> 1;
-       do {
-               writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-
-       if (uart_circ_empty(xmit))
-               pl010_stop_tx(port);
+       uart_port_tx_limited(port, ch, port->fifosize >> 1,
+               true,
+               writel(ch, port->membase + UART01x_DR),
+               ({}));
 }
 
 static void pl010_modem_status(struct uart_amba_port *uap)
index 450f4edfda0f00a1fb36910d26b2ad5202489015..915ee4b0d594944eecbf1615aa4ecd8330f10e23 100644 (file)
@@ -122,36 +122,12 @@ static void apbuart_rx_chars(struct uart_port *port)
 
 static void apbuart_tx_chars(struct uart_port *port)
 {
-       struct circ_buf *xmit = &port->state->xmit;
-       int count;
-
-       if (port->x_char) {
-               UART_PUT_CHAR(port, port->x_char);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               apbuart_stop_tx(port);
-               return;
-       }
-
-       /* amba: fill FIFO */
-       count = port->fifosize >> 1;
-       do {
-               UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               apbuart_stop_tx(port);
+       uart_port_tx_limited(port, ch, port->fifosize >> 1,
+               true,
+               UART_PUT_CHAR(port, ch),
+               ({}));
 }
 
 static irqreturn_t apbuart_int(int irq, void *dev_id)
index 5d9737c2d1f2c8ec0f2ef1bd73061ad9aea623e4..62bc7244dc67f4c9afe08a786b6a9c47df33fe69 100644 (file)
@@ -303,53 +303,24 @@ static void bcm_uart_do_rx(struct uart_port *port)
  */
 static void bcm_uart_do_tx(struct uart_port *port)
 {
-       struct circ_buf *xmit;
-       unsigned int val, max_count;
-
-       if (port->x_char) {
-               bcm_uart_writel(port, port->x_char, UART_FIFO_REG);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if (uart_tx_stopped(port)) {
-               bcm_uart_stop_tx(port);
-               return;
-       }
-
-       xmit = &port->state->xmit;
-       if (uart_circ_empty(xmit))
-               goto txq_empty;
+       unsigned int val;
+       bool pending;
+       u8 ch;
 
        val = bcm_uart_readl(port, UART_MCTL_REG);
        val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT;
-       max_count = port->fifosize - val;
-
-       while (max_count--) {
-               unsigned int c;
 
-               c = xmit->buf[xmit->tail];
-               bcm_uart_writel(port, c, UART_FIFO_REG);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-
-       if (uart_circ_empty(xmit))
-               goto txq_empty;
-       return;
+       pending = uart_port_tx_limited(port, ch, port->fifosize - val,
+               true,
+               bcm_uart_writel(port, ch, UART_FIFO_REG),
+               ({}));
+       if (pending)
+               return;
 
-txq_empty:
        /* nothing to send, disable transmit interrupt */
        val = bcm_uart_readl(port, UART_IR_REG);
        val &= ~UART_TX_INT_MASK;
        bcm_uart_writel(port, val, UART_IR_REG);
-       return;
 }
 
 /*
index ed0e763f622a880c448da1b323c05eeb507e10c7..85ce1e9af44aee4b2929c09e45c8004bae9fc41c 100644 (file)
@@ -171,6 +171,13 @@ static void mux_break_ctl(struct uart_port *port, int break_state)
 {
 }
 
+static void mux_tx_done(struct uart_port *port)
+{
+       /* FIXME js: really needs to wait? */
+       while (UART_GET_FIFO_CNT(port))
+               udelay(1);
+}
+
 /**
  * mux_write - Write chars to the mux fifo.
  * @port: Ptr to the uart_port.
@@ -180,39 +187,13 @@ static void mux_break_ctl(struct uart_port *port, int break_state)
  */
 static void mux_write(struct uart_port *port)
 {
-       int count;
-       struct circ_buf *xmit = &port->state->xmit;
-
-       if(port->x_char) {
-               UART_PUT_CHAR(port, port->x_char);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               mux_stop_tx(port);
-               return;
-       }
-
-       count = (port->fifosize) - UART_GET_FIFO_CNT(port);
-       do {
-               UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if(uart_circ_empty(xmit))
-                       break;
-
-       } while(--count > 0);
-
-       while(UART_GET_FIFO_CNT(port)) 
-               udelay(1);
-
-       if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               mux_stop_tx(port);
+       uart_port_tx_limited(port, ch,
+               port->fifosize - UART_GET_FIFO_CNT(port),
+               true,
+               UART_PUT_CHAR(port, ch),
+               mux_tx_done(port));
 }
 
 /**
index ba16e1da6bd3e74cf2a4996a297d5313ef7acc8d..7b566404cb331f813f1a6cd9600bfc65bf45bed0 100644 (file)
@@ -335,40 +335,12 @@ ignore_char:
 
 static void mvebu_uart_tx_chars(struct uart_port *port, unsigned int status)
 {
-       struct circ_buf *xmit = &port->state->xmit;
-       unsigned int count;
-       unsigned int st;
-
-       if (port->x_char) {
-               writel(port->x_char, port->membase + UART_TSH(port));
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               mvebu_uart_stop_tx(port);
-               return;
-       }
-
-       for (count = 0; count < port->fifosize; count++) {
-               writel(xmit->buf[xmit->tail], port->membase + UART_TSH(port));
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-
-               if (uart_circ_empty(xmit))
-                       break;
-
-               st = readl(port->membase + UART_STAT);
-               if (st & STAT_TX_FIFO_FUL)
-                       break;
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               mvebu_uart_stop_tx(port);
+       uart_port_tx_limited(port, ch, port->fifosize,
+               !(readl(port->membase + UART_STAT) & STAT_TX_FIFO_FUL),
+               writel(ch, port->membase + UART_TSH(port)),
+               ({}));
 }
 
 static irqreturn_t mvebu_uart_isr(int irq, void *dev_id)
index 7d0d2718ef5953962917617395e630621f5044e3..82d35dbbfa6cbb471d476efee3beb15cb6c0acba 100644 (file)
@@ -347,34 +347,12 @@ static void serial_omap_put_char(struct uart_omap_port *up, unsigned char ch)
 
 static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
 {
-       struct circ_buf *xmit = &up->port.state->xmit;
-       int count;
+       u8 ch;
 
-       if (up->port.x_char) {
-               serial_omap_put_char(up, up->port.x_char);
-               up->port.icount.tx++;
-               up->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-               serial_omap_stop_tx(&up->port);
-               return;
-       }
-       count = up->port.fifosize / 4;
-       do {
-               serial_omap_put_char(up, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               up->port.icount.tx++;
-
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-
-       if (uart_circ_empty(xmit))
-               serial_omap_stop_tx(&up->port);
+       uart_port_tx_limited(&up->port, ch, up->port.fifosize / 4,
+               true,
+               serial_omap_put_char(up, ch),
+               ({}));
 }
 
 static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
index 2d25231fad847c849f0e44b76f495eb602b5bf4d..444fa4b654aca487a0383727eff632f360567a6b 100644 (file)
@@ -174,35 +174,12 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status)
 
 static void transmit_chars(struct uart_pxa_port *up)
 {
-       struct circ_buf *xmit = &up->port.state->xmit;
-       int count;
+       u8 ch;
 
-       if (up->port.x_char) {
-               serial_out(up, UART_TX, up->port.x_char);
-               up->port.icount.tx++;
-               up->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-               serial_pxa_stop_tx(&up->port);
-               return;
-       }
-
-       count = up->port.fifosize / 2;
-       do {
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               up->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-
-
-       if (uart_circ_empty(xmit))
-               serial_pxa_stop_tx(&up->port);
+       uart_port_tx_limited(&up->port, ch, up->port.fifosize / 2,
+               true,
+               serial_out(up, UART_TX, ch),
+               ({}));
 }
 
 static void serial_pxa_start_tx(struct uart_port *port)
index b81afb06f1f40ae8d6cd9fd86a6b657bdfc460cf..749b873a5d99b9e0293cbce141108836e3ee3dca 100644 (file)
@@ -427,32 +427,13 @@ static void rp2_rx_chars(struct rp2_uart_port *up)
 
 static void rp2_tx_chars(struct rp2_uart_port *up)
 {
-       u16 max_tx = FIFO_SIZE - readw(up->base + RP2_TX_FIFO_COUNT);
-       struct circ_buf *xmit = &up->port.state->xmit;
+       u8 ch;
 
-       if (uart_tx_stopped(&up->port)) {
-               rp2_uart_stop_tx(&up->port);
-               return;
-       }
-
-       for (; max_tx != 0; max_tx--) {
-               if (up->port.x_char) {
-                       writeb(up->port.x_char, up->base + RP2_DATA_BYTE);
-                       up->port.x_char = 0;
-                       up->port.icount.tx++;
-                       continue;
-               }
-               if (uart_circ_empty(xmit)) {
-                       rp2_uart_stop_tx(&up->port);
-                       break;
-               }
-               writeb(xmit->buf[xmit->tail], up->base + RP2_DATA_BYTE);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               up->port.icount.tx++;
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
+       uart_port_tx_limited(&up->port, ch,
+               FIFO_SIZE - readw(up->base + RP2_TX_FIFO_COUNT),
+               true,
+               writeb(ch, up->base + RP2_DATA_BYTE),
+               ({}));
 }
 
 static void rp2_ch_interrupt(struct rp2_uart_port *up)
index e12f1dc18c38bc7627cf18a74920a889222ae0e9..eab387b01e36ff8ff57070a9d5809e2974b2140f 100644 (file)
@@ -321,34 +321,12 @@ receive_chars(struct uart_port *up, unsigned int *status)
 
 static inline void transmit_chars(struct uart_port *up)
 {
-       struct circ_buf *xmit = &up->state->xmit;
-       int count;
+       u8 ch;
 
-       if (up->x_char) {
-               sio_out(up, TXX9_SITFIFO, up->x_char);
-               up->icount.tx++;
-               up->x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
-               serial_txx9_stop_tx(up);
-               return;
-       }
-
-       count = TXX9_SIO_TX_FIFO;
-       do {
-               sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               up->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(up);
-
-       if (uart_circ_empty(xmit))
-               serial_txx9_stop_tx(up);
+       uart_port_tx_limited(up, ch, TXX9_SIO_TX_FIFO,
+               true,
+               sio_out(up, TXX9_SITFIFO, ch),
+               ({}));
 }
 
 static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
index 7fb6760b5c37ad87a1740fb77ead0715afc8210b..1f565a216e748c940db0132c23cccd824a0f7bcb 100644 (file)
@@ -288,33 +288,12 @@ static void __ssp_transmit_char(struct sifive_serial_port *ssp, int ch)
  */
 static void __ssp_transmit_chars(struct sifive_serial_port *ssp)
 {
-       struct circ_buf *xmit = &ssp->port.state->xmit;
-       int count;
-
-       if (ssp->port.x_char) {
-               __ssp_transmit_char(ssp, ssp->port.x_char);
-               ssp->port.icount.tx++;
-               ssp->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&ssp->port)) {
-               sifive_serial_stop_tx(&ssp->port);
-               return;
-       }
-       count = SIFIVE_TX_FIFO_DEPTH;
-       do {
-               __ssp_transmit_char(ssp, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               ssp->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&ssp->port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               sifive_serial_stop_tx(&ssp->port);
+       uart_port_tx_limited(&ssp->port, ch, SIFIVE_TX_FIFO_DEPTH,
+               true,
+               __ssp_transmit_char(ssp, ch),
+               ({}));
 }
 
 /**
index 342a87967631575f1d857201328e76c9b8fdad55..3f34f7bb77002c1d70821c9a0e65bf4cf2ea8091 100644 (file)
@@ -626,35 +626,12 @@ static inline void sprd_rx(struct uart_port *port)
 
 static inline void sprd_tx(struct uart_port *port)
 {
-       struct circ_buf *xmit = &port->state->xmit;
-       int count;
-
-       if (port->x_char) {
-               serial_out(port, SPRD_TXD, port->x_char);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               sprd_stop_tx(port);
-               return;
-       }
-
-       count = THLD_TX_EMPTY;
-       do {
-               serial_out(port, SPRD_TXD, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               sprd_stop_tx(port);
+       uart_port_tx_limited(port, ch, THLD_TX_EMPTY,
+               true,
+               serial_out(port, SPRD_TXD, ch),
+               ({}));
 }
 
 /* this handles the interrupt from one port */
index fcecea689a0ddd3e52bcebf887b7c6c027c515e8..5215e6910f6869f0eb3d4dafd1ad87e5aea37fa5 100644 (file)
@@ -237,50 +237,12 @@ static inline unsigned asc_hw_txroom(struct uart_port *port)
  */
 static void asc_transmit_chars(struct uart_port *port)
 {
-       struct circ_buf *xmit = &port->state->xmit;
-       int txroom;
-       unsigned char c;
-
-       txroom = asc_hw_txroom(port);
-
-       if ((txroom != 0) && port->x_char) {
-               c = port->x_char;
-               port->x_char = 0;
-               asc_out(port, ASC_TXBUF, c);
-               port->icount.tx++;
-               txroom = asc_hw_txroom(port);
-       }
-
-       if (uart_tx_stopped(port)) {
-               /*
-                * We should try and stop the hardware here, but I
-                * don't think the ASC has any way to do that.
-                */
-               asc_disable_tx_interrupts(port);
-               return;
-       }
-
-       if (uart_circ_empty(xmit)) {
-               asc_disable_tx_interrupts(port);
-               return;
-       }
-
-       if (txroom == 0)
-               return;
-
-       do {
-               c = xmit->buf[xmit->tail];
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               asc_out(port, ASC_TXBUF, c);
-               port->icount.tx++;
-               txroom--;
-       } while ((txroom > 0) && (!uart_circ_empty(xmit)));
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
+       u8 ch;
 
-       if (uart_circ_empty(xmit))
-               asc_disable_tx_interrupts(port);
+       uart_port_tx_limited(port, ch, asc_hw_txroom(port),
+               true,
+               asc_out(port, ASC_TXBUF, ch),
+               ({}));
 }
 
 static void asc_receive_chars(struct uart_port *port)