From: Michael.McTernan.2001@cs.bris.ac.uk (Michael McTernan)
To: linux-arm-kernel@lists.infradead.org
Subject: ARM: iMX: lockup with irqs disabled in drivers/tty/imx.c
Date: Sun, 20 May 2012 12:04:27 +0100 [thread overview]
Message-ID: <4FB8CFBB.2020004@cs.bris.ac.uk> (raw)
Hi All,
I've found a lockup (interrupts disabled, infinite loop) in
drivers/tty/imx.c. This is on i.MX53 (Karo module), using the Karo BSP,
but having checked the arm-soc git tree, I think the bug is here too.
The Linaro tree(s) look the same.
I see the problem when the UART is setup to not have rtscts, so
port->have_rtscts = 0 in the driver. Additionally there is nothing
hanging on the serial port (in my case the peripheral isn't yet powered
up) so the rx line is low.
I can then trigger the lockup by simply booting the unit and issuing
"echo > /dev/ttymxc1". The same can be done on the other ports too.
Once locked, magic sys-req appears not to work, pinging the target is
dead etc...
The sequence of events in the kernel goes something like this:
1) imx_startup()
2) imx_int()
\-> imx_rxint()
|-> URXD0 returns 0xd800
\-> tty_insert_flip_char(tty, 0, TTY_BREAK)
...
3) imx_start_tx()
\-> imx_transmit_buffer()
Writes '^' '@'
4) imx_set_termios()
\-> hangs when waiting for USR2_TXDC
The problem is that UCR2_IRTS isn't yet set (that comes later in
imx_set_termios()), so the transmitter is waiting for the pin to be
asserted before it can serialise out from its FIFO and set the USR2_TXDC
bit. Since CTS/RTS will never come on this port, we end up spinning in
the following bit of code in imx_set_termios():948, having earlier
called spin_lock_irqsave():
while ( !(readl(sport->port.membase + USR2) & USR2_TXDC))
barrier();
The tx was a surprise to me; it looks like the receiver sees the low rx
pin as a break which then, I think, causes a local echo sending back
'^@', as per the following stack:
(imx_start_tx+0x60/0x12c) from (__uart_start+0x44/0x48)
(__uart_start+0x44/0x48) from (uart_start+0x20/0x4c)
(uart_start+0x20/0x4c) from (process_echoes+0x25c/0x260)
(process_echoes+0x25c/0x260) from (n_tty_receive_buf+0xc90/0xf04)
(n_tty_receive_buf+0xc90/0xf04) from (flush_to_ldisc+0xfc/0x1b0)
(flush_to_ldisc+0xfc/0x1b0) from (process_one_work+0x1fc/0x330)
(process_one_work+0x1fc/0x330) from (worker_thread+0x1d0/0x2f8)
(worker_thread+0x1d0/0x2f8) from (kthread+0x7c/0x84)
(kthread+0x7c/0x84) from (kernel_thread_exit+0x0/0x8)
Had imx_set_termios() been called prior to the imx_transmit_buffer(),
UCR2_IRTS would have been set and disaster avoided.
So one workaround is to set UCR2_IRTS in imx_startup() as per the patch
on the end of this email. This still wouldn't cater for other cases
where RTS/CTS is in use but not asserted by a peripheral (or the pin
mux/pad isn't correctly setup/routed), or that termios() is called while
data is blocked waiting for CTS/RTS. The drain loop should probably
implement a timeout and WARN(), but I'm not sure if it should also use a
completion and interrupt to be correct - other serial drivers don't
appear to do this though?
Anyway, the lockup is nasty, so hopefully can be triaged?
Regards,
Mike
Signed-off-by: Michael McTernan <Michael.McTernan.2001@cs.bris.ac.uk>
diff -Naurp orig/imx.c fixed/imx.c
--- orig/imx.c 2012-05-20 10:37:20.320041462 +0100
+++ fixed/imx.c 2012-05-20 11:18:28.512657377 +0100
@@ -741,6 +741,9 @@ static int imx_startup(struct uart_port
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR2);
+ if (!sport->have_rtscts) {
+ temp |= UCR2_IRTS;
+ }
temp |= (UCR2_RXEN | UCR2_TXEN);
writel(temp, sport->port.membase + UCR2);
next reply other threads:[~2012-05-20 11:04 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-20 11:04 Michael McTernan [this message]
2012-06-04 16:54 ` ARM: iMX: lockup with irqs disabled in drivers/tty/imx.c manfred.schlaegl at gmx.at
2012-06-10 17:38 ` Fabio Estevam
2012-06-12 18:53 ` Fabio Estevam
2012-06-15 8:36 ` Michael McTernan
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=4FB8CFBB.2020004@cs.bris.ac.uk \
--to=michael.mcternan.2001@cs.bris.ac.uk \
--cc=linux-arm-kernel@lists.infradead.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.