From: Nicolas Ferre <nicolas.ferre@atmel.com>
To: <mark.roszko@gmail.com>, <gregkh@linuxfoundation.org>,
<leilei.zhao@atmel.com>
Cc: <mdeneen@gmail.com>, <linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <linux-serial@vger.kernel.org>,
stable <stable@vger.kernel.org>,
Nicolas Ferre <nicolas.ferre@atmel.com>
Subject: [RFC PATCH] tty/serial: at91: disable uart timer at start of shutdown
Date: Wed, 8 Jan 2014 11:28:36 +0100 [thread overview]
Message-ID: <1389176916-6114-1-git-send-email-nicolas.ferre@atmel.com> (raw)
In-Reply-To: <CAJjB1qLBoXA_XeEV+qU6pi0JVS+==kVA7mEDuAufrYup3htU2g@mail.gmail.com>
From: Marek Roszko <mark.roszko@gmail.com>
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>
---
Hi Marek,
This is my modified version of your patch.
* I adapted it to the mainline kernel
* I rewrote the commit message
* I used setup_timer() / del_timer_sync() in any case, even the
!DMA/!PDC case. Otherwise, the time would have been deleted in
an uninitialized state which may lead to errors (I didn't checked
though).
Can you please tell me how do you feel with this patch (and the commit message)
and if it solves the issue that you encounter on your side.
Best regards,
drivers/tty/serial/atmel_serial.c | 22 ++++++++++------------
1 file 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)
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)
@@ -1229,9 +1226,6 @@ static void atmel_release_rx_pdc(struct uart_port *port)
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)
@@ -1604,12 +1598,13 @@ static int atmel_startup(struct uart_port *port)
/* 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 */
@@ -1624,9 +1619,6 @@ static int atmel_startup(struct uart_port *port)
} 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 */
@@ -1652,6 +1644,12 @@ static void atmel_shutdown(struct uart_port *port)
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
*/
--
1.8.2.2
next parent reply other threads:[~2014-01-08 10:28 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CAJjB1qLBoXA_XeEV+qU6pi0JVS+==kVA7mEDuAufrYup3htU2g@mail.gmail.com>
2014-01-08 10:28 ` Nicolas Ferre [this message]
2014-01-08 14:29 ` Mark Roszko
2014-01-09 7:08 ` Mark Roszko
2014-01-10 9:34 ` Nicolas Ferre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1389176916-6114-1-git-send-email-nicolas.ferre@atmel.com \
--to=nicolas.ferre@atmel.com \
--cc=gregkh@linuxfoundation.org \
--cc=leilei.zhao@atmel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=mark.roszko@gmail.com \
--cc=mdeneen@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®