Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: timbuart: make sure last byte is sent when port is closed

Fix a problem in early versions of the FPGA IP.

In certain situations the IP reports that the FIFO is empty, but a byte is
still clocked out. If a flush is done at that point the currently clocked
byte is canceled.

This causes incompatibilities with the upper layers when a port is closed,
it waits until the FIFO is empty and then closes the port. During close
the FIFO is flushed -> the last byte is not sent properly.

Now the FIFO is only flushed if it is reported to be non-empty. Which
makes the currently clocked out byte to finish.

[akpm@linux-foundation.org: fix build]
Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Richard Röjfors and committed by
Greg Kroah-Hartman
24cd73a3 44051996

+13 -10
+13 -10
drivers/serial/timbuart.c
··· 68 68 tasklet_schedule(&uart->tasklet); 69 69 } 70 70 71 + static unsigned int timbuart_tx_empty(struct uart_port *port) 72 + { 73 + u32 isr = ioread32(port->membase + TIMBUART_ISR); 74 + 75 + return (isr & TXBE) ? TIOCSER_TEMT : 0; 76 + } 77 + 71 78 static void timbuart_flush_buffer(struct uart_port *port) 72 79 { 73 - u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX; 80 + if (!timbuart_tx_empty(port)) { 81 + u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 82 + TIMBUART_CTRL_FLSHTX; 74 83 75 - iowrite8(ctl, port->membase + TIMBUART_CTRL); 76 - iowrite32(TXBF, port->membase + TIMBUART_ISR); 84 + iowrite8(ctl, port->membase + TIMBUART_CTRL); 85 + iowrite32(TXBF, port->membase + TIMBUART_ISR); 86 + } 77 87 } 78 88 79 89 static void timbuart_rx_chars(struct uart_port *port) ··· 203 193 204 194 spin_unlock(&uart->port.lock); 205 195 dev_dbg(uart->port.dev, "%s leaving\n", __func__); 206 - } 207 - 208 - static unsigned int timbuart_tx_empty(struct uart_port *port) 209 - { 210 - u32 isr = ioread32(port->membase + TIMBUART_ISR); 211 - 212 - return (isr & TXBE) ? TIOCSER_TEMT : 0; 213 196 } 214 197 215 198 static unsigned int timbuart_get_mctrl(struct uart_port *port)