diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2014-10-16 16:54:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-05 21:53:54 -0500 |
commit | 479e9b94fdce7bc46f669831012fc12f56696fd7 (patch) | |
tree | e51d28533aa68a3234e0ce4a6f21bb5b59417997 | |
parent | 86c80a8e2ab443e9c4261b3499de4ce808399104 (diff) |
serial: Refactor uart_flush_buffer() from uart_close()
In the context of the final tty & port close, flushing the tx
ring buffer after the hardware has already been shutdown and
the ring buffer freed is neither required nor desirable.
uart_flush_buffer() performs 3 operations:
1. Resets tx ring buffer indices, but the tx ring buffer has
already been freed and the indices are reset if the port is
re-opened.
2. Calls uart driver's flush_buffer() method
5 in-tree uart drivers define flush_buffer() methods:
amba-pl011, atmel-serial, imx, serial-tegra, timbuart
These have been refactored into the shutdown() method, if
required.
3. Kicks the ldisc for more writing, but this is undesirable.
The file handle is being released; any waiting writer will
will be kicked out by tty_release() with a warning. Further,
the N_TTY ldisc may generate SIGIO for a file handle which
is no longer valid.
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 1 | ||||
-rw-r--r-- | drivers/tty/serial/atmel_serial.c | 28 | ||||
-rw-r--r-- | drivers/tty/serial/serial-tegra.c | 30 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 1 | ||||
-rw-r--r-- | drivers/tty/serial/timbuart.c | 2 |
5 files changed, 34 insertions, 28 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 02016fcd91b8..8469b66ff832 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -1689,6 +1689,7 @@ static void pl011_shutdown(struct uart_port *port) | |||
1689 | plat->exit(); | 1689 | plat->exit(); |
1690 | } | 1690 | } |
1691 | 1691 | ||
1692 | pl011_dma_flush_buffer(port); | ||
1692 | } | 1693 | } |
1693 | 1694 | ||
1694 | static void | 1695 | static void |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index edde3eca055d..8a84034d130c 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -1802,6 +1802,20 @@ free_irq: | |||
1802 | } | 1802 | } |
1803 | 1803 | ||
1804 | /* | 1804 | /* |
1805 | * Flush any TX data submitted for DMA. Called when the TX circular | ||
1806 | * buffer is reset. | ||
1807 | */ | ||
1808 | static void atmel_flush_buffer(struct uart_port *port) | ||
1809 | { | ||
1810 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
1811 | |||
1812 | if (atmel_use_pdc_tx(port)) { | ||
1813 | UART_PUT_TCR(port, 0); | ||
1814 | atmel_port->pdc_tx.ofs = 0; | ||
1815 | } | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1805 | * Disable the port | 1819 | * Disable the port |
1806 | */ | 1820 | */ |
1807 | static void atmel_shutdown(struct uart_port *port) | 1821 | static void atmel_shutdown(struct uart_port *port) |
@@ -1852,20 +1866,8 @@ static void atmel_shutdown(struct uart_port *port) | |||
1852 | atmel_free_gpio_irq(port); | 1866 | atmel_free_gpio_irq(port); |
1853 | 1867 | ||
1854 | atmel_port->ms_irq_enabled = false; | 1868 | atmel_port->ms_irq_enabled = false; |
1855 | } | ||
1856 | 1869 | ||
1857 | /* | 1870 | atmel_flush_buffer(port); |
1858 | * Flush any TX data submitted for DMA. Called when the TX circular | ||
1859 | * buffer is reset. | ||
1860 | */ | ||
1861 | static void atmel_flush_buffer(struct uart_port *port) | ||
1862 | { | ||
1863 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
1864 | |||
1865 | if (atmel_use_pdc_tx(port)) { | ||
1866 | UART_PUT_TCR(port, 0); | ||
1867 | atmel_port->pdc_tx.ofs = 0; | ||
1868 | } | ||
1869 | } | 1871 | } |
1870 | 1872 | ||
1871 | /* | 1873 | /* |
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 53d7c31ce098..78a5cf65bf02 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c | |||
@@ -1034,6 +1034,20 @@ fail_rx_dma: | |||
1034 | return ret; | 1034 | return ret; |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | /* | ||
1038 | * Flush any TX data submitted for DMA and PIO. Called when the | ||
1039 | * TX circular buffer is reset. | ||
1040 | */ | ||
1041 | static void tegra_uart_flush_buffer(struct uart_port *u) | ||
1042 | { | ||
1043 | struct tegra_uart_port *tup = to_tegra_uport(u); | ||
1044 | |||
1045 | tup->tx_bytes = 0; | ||
1046 | if (tup->tx_dma_chan) | ||
1047 | dmaengine_terminate_all(tup->tx_dma_chan); | ||
1048 | return; | ||
1049 | } | ||
1050 | |||
1037 | static void tegra_uart_shutdown(struct uart_port *u) | 1051 | static void tegra_uart_shutdown(struct uart_port *u) |
1038 | { | 1052 | { |
1039 | struct tegra_uart_port *tup = to_tegra_uport(u); | 1053 | struct tegra_uart_port *tup = to_tegra_uport(u); |
@@ -1046,6 +1060,8 @@ static void tegra_uart_shutdown(struct uart_port *u) | |||
1046 | tegra_uart_dma_channel_free(tup, true); | 1060 | tegra_uart_dma_channel_free(tup, true); |
1047 | tegra_uart_dma_channel_free(tup, false); | 1061 | tegra_uart_dma_channel_free(tup, false); |
1048 | free_irq(u->irq, tup); | 1062 | free_irq(u->irq, tup); |
1063 | |||
1064 | tegra_uart_flush_buffer(u); | ||
1049 | } | 1065 | } |
1050 | 1066 | ||
1051 | static void tegra_uart_enable_ms(struct uart_port *u) | 1067 | static void tegra_uart_enable_ms(struct uart_port *u) |
@@ -1174,20 +1190,6 @@ static void tegra_uart_set_termios(struct uart_port *u, | |||
1174 | return; | 1190 | return; |
1175 | } | 1191 | } |
1176 | 1192 | ||
1177 | /* | ||
1178 | * Flush any TX data submitted for DMA and PIO. Called when the | ||
1179 | * TX circular buffer is reset. | ||
1180 | */ | ||
1181 | static void tegra_uart_flush_buffer(struct uart_port *u) | ||
1182 | { | ||
1183 | struct tegra_uart_port *tup = to_tegra_uport(u); | ||
1184 | |||
1185 | tup->tx_bytes = 0; | ||
1186 | if (tup->tx_dma_chan) | ||
1187 | dmaengine_terminate_all(tup->tx_dma_chan); | ||
1188 | return; | ||
1189 | } | ||
1190 | |||
1191 | static const char *tegra_uart_type(struct uart_port *u) | 1193 | static const char *tegra_uart_type(struct uart_port *u) |
1192 | { | 1194 | { |
1193 | return TEGRA_UART_TYPE; | 1195 | return TEGRA_UART_TYPE; |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1166c52e51f4..787d67f74bd9 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -1361,7 +1361,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1361 | 1361 | ||
1362 | mutex_lock(&port->mutex); | 1362 | mutex_lock(&port->mutex); |
1363 | uart_shutdown(tty, state); | 1363 | uart_shutdown(tty, state); |
1364 | uart_flush_buffer(tty); | ||
1365 | 1364 | ||
1366 | tty_ldisc_flush(tty); | 1365 | tty_ldisc_flush(tty); |
1367 | 1366 | ||
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c index 0d11d5032b93..e9e252324fb6 100644 --- a/drivers/tty/serial/timbuart.c +++ b/drivers/tty/serial/timbuart.c | |||
@@ -273,6 +273,8 @@ static void timbuart_shutdown(struct uart_port *port) | |||
273 | dev_dbg(port->dev, "%s\n", __func__); | 273 | dev_dbg(port->dev, "%s\n", __func__); |
274 | free_irq(port->irq, uart); | 274 | free_irq(port->irq, uart); |
275 | iowrite32(0, port->membase + TIMBUART_IER); | 275 | iowrite32(0, port->membase + TIMBUART_IER); |
276 | |||
277 | timbuart_flush_buffer(port); | ||
276 | } | 278 | } |
277 | 279 | ||
278 | static int get_bindex(int baud) | 280 | static int get_bindex(int baud) |