aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Roszko <mark.roszko@gmail.com>2014-01-10 04:33:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-13 18:55:59 -0500
commit8bc661bfc0c2d221e209f4205bdaaf574d50100c (patch)
tree2fbd2b8a47104ebc014476530806b1afbbe2f2f5
parent3685f19e07802ec4207b52465c408f185b66490e (diff)
tty/serial: at91: disable uart timer at start of shutdown
The uart timer will schedule a tasklet when it fires. It is possible that it can fire inside _shutdown before it is killed in the dma and pdc cleanup routines. This causes a tasklet that exists after the port is shutdown, so when the kernel finally executes it, it panics as the tty port is NULL. This is a somewhat rare condition but its possible if a program keeps on opening/closing the port. It has been observed in particular with systemd boot messages that were causing a kernel panic because of this behavior. Moving the timer deletion to the beginning of the function stops a tasklet from being scheduled unexpectedly. Signed-off-by: Marek Roszko <mark.roszko@gmail.com> Cc: stable <stable@vger.kernel.org> # v3.12 [nicolas.ferre@atmel.com: modify commit message, call setup_timer() in any case] Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/atmel_serial.c22
1 files changed, 10 insertions, 12 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2b6ac1be00d3..a49f10d269b2 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -825,9 +825,6 @@ static void atmel_release_rx_dma(struct uart_port *port)
825 atmel_port->desc_rx = NULL; 825 atmel_port->desc_rx = NULL;
826 atmel_port->chan_rx = NULL; 826 atmel_port->chan_rx = NULL;
827 atmel_port->cookie_rx = -EINVAL; 827 atmel_port->cookie_rx = -EINVAL;
828
829 if (!atmel_port->is_usart)
830 del_timer_sync(&atmel_port->uart_timer);
831} 828}
832 829
833static void atmel_rx_from_dma(struct uart_port *port) 830static void atmel_rx_from_dma(struct uart_port *port)
@@ -1229,9 +1226,6 @@ static void atmel_release_rx_pdc(struct uart_port *port)
1229 DMA_FROM_DEVICE); 1226 DMA_FROM_DEVICE);
1230 kfree(pdc->buf); 1227 kfree(pdc->buf);
1231 } 1228 }
1232
1233 if (!atmel_port->is_usart)
1234 del_timer_sync(&atmel_port->uart_timer);
1235} 1229}
1236 1230
1237static void atmel_rx_from_pdc(struct uart_port *port) 1231static void atmel_rx_from_pdc(struct uart_port *port)
@@ -1604,12 +1598,13 @@ static int atmel_startup(struct uart_port *port)
1604 /* enable xmit & rcvr */ 1598 /* enable xmit & rcvr */
1605 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); 1599 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
1606 1600
1601 setup_timer(&atmel_port->uart_timer,
1602 atmel_uart_timer_callback,
1603 (unsigned long)port);
1604
1607 if (atmel_use_pdc_rx(port)) { 1605 if (atmel_use_pdc_rx(port)) {
1608 /* set UART timeout */ 1606 /* set UART timeout */
1609 if (!atmel_port->is_usart) { 1607 if (!atmel_port->is_usart) {
1610 setup_timer(&atmel_port->uart_timer,
1611 atmel_uart_timer_callback,
1612 (unsigned long)port);
1613 mod_timer(&atmel_port->uart_timer, 1608 mod_timer(&atmel_port->uart_timer,
1614 jiffies + uart_poll_timeout(port)); 1609 jiffies + uart_poll_timeout(port));
1615 /* set USART timeout */ 1610 /* set USART timeout */
@@ -1624,9 +1619,6 @@ static int atmel_startup(struct uart_port *port)
1624 } else if (atmel_use_dma_rx(port)) { 1619 } else if (atmel_use_dma_rx(port)) {
1625 /* set UART timeout */ 1620 /* set UART timeout */
1626 if (!atmel_port->is_usart) { 1621 if (!atmel_port->is_usart) {
1627 setup_timer(&atmel_port->uart_timer,
1628 atmel_uart_timer_callback,
1629 (unsigned long)port);
1630 mod_timer(&atmel_port->uart_timer, 1622 mod_timer(&atmel_port->uart_timer,
1631 jiffies + uart_poll_timeout(port)); 1623 jiffies + uart_poll_timeout(port));
1632 /* set USART timeout */ 1624 /* set USART timeout */
@@ -1652,6 +1644,12 @@ static void atmel_shutdown(struct uart_port *port)
1652 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 1644 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
1653 1645
1654 /* 1646 /*
1647 * Prevent any tasklets being scheduled during
1648 * cleanup
1649 */
1650 del_timer_sync(&atmel_port->uart_timer);
1651
1652 /*
1655 * Clear out any scheduled tasklets before 1653 * Clear out any scheduled tasklets before
1656 * we destroy the buffers 1654 * we destroy the buffers
1657 */ 1655 */