summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2013-07-04 09:28:51 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-26 23:33:59 (GMT)
commitd970d7fe65adff5efe75b4a73c4ffc9be57089f7 (patch)
tree3dc57f349b1c3e248a9054f004344494c2da100d /drivers/tty
parent3bf5d350586d98eb28ab7f86ffbd66518ffd95d8 (diff)
downloadlinux-fsl-qoriq-d970d7fe65adff5efe75b4a73c4ffc9be57089f7.tar.xz
serial/mxs-auart: fix race condition in interrupt handler
The handler needs to ack the pending events before actually handling them. Otherwise a new event might come in after it it considered non-pending or handled and is acked then without being handled. So this event is only noticed when the next interrupt happens. Without this patch an i.MX28 based machine running an rt-patched kernel regularly hangs during boot. Cc: stable@vger.kernel.org # v2.6.39+ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/mxs-auart.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 4f5f161..3de0fb2 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -678,11 +678,18 @@ static void mxs_auart_settermios(struct uart_port *u,
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
{
- u32 istatus, istat;
+ u32 istat;
struct mxs_auart_port *s = context;
u32 stat = readl(s->port.membase + AUART_STAT);
- istatus = istat = readl(s->port.membase + AUART_INTR);
+ istat = readl(s->port.membase + AUART_INTR);
+
+ /* ack irq */
+ writel(istat & (AUART_INTR_RTIS
+ | AUART_INTR_TXIS
+ | AUART_INTR_RXIS
+ | AUART_INTR_CTSMIS),
+ s->port.membase + AUART_INTR_CLR);
if (istat & AUART_INTR_CTSMIS) {
uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
@@ -702,12 +709,6 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
istat &= ~AUART_INTR_TXIS;
}
- writel(istatus & (AUART_INTR_RTIS
- | AUART_INTR_TXIS
- | AUART_INTR_RXIS
- | AUART_INTR_CTSMIS),
- s->port.membase + AUART_INTR_CLR);
-
return IRQ_HANDLED;
}