lkml.org 
[lkml]   [2014]   [Feb]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 058/133] tty/serial: at91: disable uart timer at start of shutdown
    Date
    3.12-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Marek Roszko <mark.roszko@gmail.com>

    commit 8bc661bfc0c2d221e209f4205bdaaf574d50100c upstream.

    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>
    [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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/tty/serial/atmel_serial.c | 22 ++++++++++------------
    1 file changed, 10 insertions(+), 12 deletions(-)

    --- a/drivers/tty/serial/atmel_serial.c
    +++ b/drivers/tty/serial/atmel_serial.c
    @@ -824,9 +824,6 @@ static void atmel_release_rx_dma(struct
    atmel_port->desc_rx = NULL;
    atmel_port->chan_rx = NULL;
    atmel_port->cookie_rx = -EINVAL;
    -
    - if (!atmel_port->is_usart)
    - del_timer_sync(&atmel_port->uart_timer);
    }

    static void atmel_rx_from_dma(struct uart_port *port)
    @@ -1228,9 +1225,6 @@ static void atmel_release_rx_pdc(struct
    DMA_FROM_DEVICE);
    kfree(pdc->buf);
    }
    -
    - if (!atmel_port->is_usart)
    - del_timer_sync(&atmel_port->uart_timer);
    }

    static void atmel_rx_from_pdc(struct uart_port *port)
    @@ -1587,12 +1581,13 @@ static int atmel_startup(struct uart_por
    /* enable xmit & rcvr */
    UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);

    + setup_timer(&atmel_port->uart_timer,
    + atmel_uart_timer_callback,
    + (unsigned long)port);
    +
    if (atmel_use_pdc_rx(port)) {
    /* set UART timeout */
    if (!atmel_port->is_usart) {
    - setup_timer(&atmel_port->uart_timer,
    - atmel_uart_timer_callback,
    - (unsigned long)port);
    mod_timer(&atmel_port->uart_timer,
    jiffies + uart_poll_timeout(port));
    /* set USART timeout */
    @@ -1607,9 +1602,6 @@ static int atmel_startup(struct uart_por
    } else if (atmel_use_dma_rx(port)) {
    /* set UART timeout */
    if (!atmel_port->is_usart) {
    - setup_timer(&atmel_port->uart_timer,
    - atmel_uart_timer_callback,
    - (unsigned long)port);
    mod_timer(&atmel_port->uart_timer,
    jiffies + uart_poll_timeout(port));
    /* set USART timeout */
    @@ -1635,6 +1627,12 @@ static void atmel_shutdown(struct uart_p
    struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);

    /*
    + * Prevent any tasklets being scheduled during
    + * cleanup
    + */
    + del_timer_sync(&atmel_port->uart_timer);
    +
    + /*
    * Clear out any scheduled tasklets before
    * we destroy the buffers
    */



    \
     
     \ /
      Last update: 2014-02-05 09:21    [W:4.182 / U:0.180 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site