]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
serial: stm32: update PIO transmission
authorErwan Le Ray <erwan.leray@st.com>
Tue, 18 Jun 2019 10:02:23 +0000 (12:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Jun 2019 09:17:36 +0000 (11:17 +0200)
Improves PIO transmission:
- Replaces the FIFO filling per character by a filling per blocks of
  characters, which provides better performances
- Replaces the active waiting loop by TX empty interrupt dynamic handling.
  TXE interrupt is now enabled when data has to be sent (ie when
  uart_circ is not empty), and inhibited when there is no more data to
  send (ie when uart_circ is empty).

Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/stm32-usart.c

index 2e75b586e5bfdb0263160d990663d6c25eb73bdc..2085f10aabfa704a7e1b6149baba38d6234c4b07 100644 (file)
@@ -300,27 +300,26 @@ static void stm32_transmit_chars_pio(struct uart_port *port)
        struct stm32_port *stm32_port = to_stm32_port(port);
        struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
        struct circ_buf *xmit = &port->state->xmit;
-       unsigned int isr;
-       int ret;
 
        if (stm32_port->tx_dma_busy) {
                stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
                stm32_port->tx_dma_busy = false;
        }
 
-       ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
-                                               isr,
-                                               (isr & USART_SR_TXE),
-                                               10, 100000);
-
-       if (ret)
-               dev_err(port->dev, "tx empty not set\n");
-
-       stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
+       while (!uart_circ_empty(xmit)) {
+               /* Check that TDR is empty before filling FIFO */
+               if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
+                       break;
+               writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               port->icount.tx++;
+       }
 
-       writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
-       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-       port->icount.tx++;
+       /* rely on TXE irq (mask or unmask) for sending remaining data */
+       if (uart_circ_empty(xmit))
+               stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
+       else
+               stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
 }
 
 static void stm32_transmit_chars_dma(struct uart_port *port)