diff options
| author | Richard Röjfors <richard.rojfors@pelagicore.com> | 2010-04-27 17:16:34 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-21 12:34:29 -0400 |
| commit | 24cd73a3942f3df214d7953f0cfd65d5085fa583 (patch) | |
| tree | ead53b3f9d40915b629fdcef2e2af89c21c66b0b | |
| parent | 44051996230510ccb125cfa552d464950d1767b9 (diff) | |
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>
| -rw-r--r-- | drivers/serial/timbuart.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 62f389fdc2a3..67ca642713b8 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c | |||
| @@ -68,12 +68,22 @@ static void timbuart_start_tx(struct uart_port *port) | |||
| 68 | tasklet_schedule(&uart->tasklet); | 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 | static void timbuart_flush_buffer(struct uart_port *port) | 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); | 84 | iowrite8(ctl, port->membase + TIMBUART_CTRL); |
| 76 | iowrite32(TXBF, port->membase + TIMBUART_ISR); | 85 | iowrite32(TXBF, port->membase + TIMBUART_ISR); |
| 86 | } | ||
| 77 | } | 87 | } |
| 78 | 88 | ||
| 79 | static void timbuart_rx_chars(struct uart_port *port) | 89 | static void timbuart_rx_chars(struct uart_port *port) |
| @@ -195,13 +205,6 @@ void timbuart_tasklet(unsigned long arg) | |||
| 195 | dev_dbg(uart->port.dev, "%s leaving\n", __func__); | 205 | dev_dbg(uart->port.dev, "%s leaving\n", __func__); |
| 196 | } | 206 | } |
| 197 | 207 | ||
| 198 | static unsigned int timbuart_tx_empty(struct uart_port *port) | ||
| 199 | { | ||
| 200 | u32 isr = ioread32(port->membase + TIMBUART_ISR); | ||
| 201 | |||
| 202 | return (isr & TXBE) ? TIOCSER_TEMT : 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static unsigned int timbuart_get_mctrl(struct uart_port *port) | 208 | static unsigned int timbuart_get_mctrl(struct uart_port *port) |
| 206 | { | 209 | { |
| 207 | u8 cts = ioread8(port->membase + TIMBUART_CTRL); | 210 | u8 cts = ioread8(port->membase + TIMBUART_CTRL); |
