diff options
author | Huang Shijie <b32955@freescale.com> | 2013-10-11 06:30:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-16 16:19:54 -0400 |
commit | eb56b7edae6ba2bfd3a07e59ea82195e2c1c28ec (patch) | |
tree | 5fdaab8e8a4e33e2f4b63f6d82629e02a6a0a163 /drivers/tty/serial/imx.c | |
parent | fa2b5ea09e48186041f68649ab8192447b31bffc (diff) |
serial: imx: implement the flush_buffer hook
The current driver does not implement the flush_buffer hook for
uart_ops. When we enable the DMA for the driver, and test it with Bluetooth,
we may meet the following bug for TX:
[1] User application may call the flush operation at any time.
The uart_flush_buffer() calls the uart_circ_clear() to set
the xmit->head and xmit->tail with 0.
[2] The TX DMA callback can be called at any time too.
The dma_tx_call() will update the xmit->tail.
If [2] occurs just after the [1], we will get the wrong xmit->tail.
This patch implements the flush_buffer hook to fix this issue.
Signed-off-by: Huang Shijie <b32955@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r-- | drivers/tty/serial/imx.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c07d9bb39695..708ba899258d 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -1303,6 +1303,16 @@ static void imx_shutdown(struct uart_port *port) | |||
1303 | clk_disable_unprepare(sport->clk_ipg); | 1303 | clk_disable_unprepare(sport->clk_ipg); |
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | static void imx_flush_buffer(struct uart_port *port) | ||
1307 | { | ||
1308 | struct imx_port *sport = (struct imx_port *)port; | ||
1309 | |||
1310 | if (sport->dma_is_enabled) { | ||
1311 | sport->tx_bytes = 0; | ||
1312 | dmaengine_terminate_all(sport->dma_chan_tx); | ||
1313 | } | ||
1314 | } | ||
1315 | |||
1306 | static void | 1316 | static void |
1307 | imx_set_termios(struct uart_port *port, struct ktermios *termios, | 1317 | imx_set_termios(struct uart_port *port, struct ktermios *termios, |
1308 | struct ktermios *old) | 1318 | struct ktermios *old) |
@@ -1623,6 +1633,7 @@ static struct uart_ops imx_pops = { | |||
1623 | .break_ctl = imx_break_ctl, | 1633 | .break_ctl = imx_break_ctl, |
1624 | .startup = imx_startup, | 1634 | .startup = imx_startup, |
1625 | .shutdown = imx_shutdown, | 1635 | .shutdown = imx_shutdown, |
1636 | .flush_buffer = imx_flush_buffer, | ||
1626 | .set_termios = imx_set_termios, | 1637 | .set_termios = imx_set_termios, |
1627 | .type = imx_type, | 1638 | .type = imx_type, |
1628 | .release_port = imx_release_port, | 1639 | .release_port = imx_release_port, |