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 /drivers/serial/timbuart.c | |
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>
Diffstat (limited to 'drivers/serial/timbuart.c')
-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); |