* [PATCH 0/2] pch_uart: fix a deadlock and add sysrq support
@ 2013-01-19 9:52 Liang Li
2013-01-19 9:52 ` [PATCH 1/2] pch_uart: fix a deadlock when pch_uart as console Liang Li
2013-01-19 9:52 ` [PATCH 2/2] pch_uart: add sysrq support Liang Li
0 siblings, 2 replies; 3+ messages in thread
From: Liang Li @ 2013-01-19 9:52 UTC (permalink / raw)
To: linux-serial, linux-kernel
Cc: liang.li, dvhart, bruce.ashfield, tomoya.rohm, feng.tang, alan,
gregkh
Patch 1/2 is fixing a deadlock issue caused by serial error when using
pch_uart as serial console. Send brk to serial console can be used to
reproduce the issue.
Patch 2/2 is adding sysrq support for pch_uart.
Diffstat:
drivers/tty/serial/pch_uart.c | 56 ++++++++++++++++++++++++++++++------------
1 file changed, 41 insertions(+), 15 deletions(-)
---
Thanks,
Liang Li
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] pch_uart: fix a deadlock when pch_uart as console
2013-01-19 9:52 [PATCH 0/2] pch_uart: fix a deadlock and add sysrq support Liang Li
@ 2013-01-19 9:52 ` Liang Li
2013-01-19 9:52 ` [PATCH 2/2] pch_uart: add sysrq support Liang Li
1 sibling, 0 replies; 3+ messages in thread
From: Liang Li @ 2013-01-19 9:52 UTC (permalink / raw)
To: linux-serial, linux-kernel
Cc: liang.li, dvhart, bruce.ashfield, tomoya.rohm, feng.tang, alan,
gregkh
When we use pch_uart as system console like 'console=ttyPCH0,115200',
then 'send break' to it. We'll encounter the deadlock on a cpu/core,
with interrupts disabled on the core. When we happen to have all irqs
affinity to cpu0 then the deadlock on cpu0 actually deadlock whole
system.
In pch_uart_interrupt, we have spin_lock_irqsave(&priv->lock, flags)
then call pch_uart_err_ir when break is received. Then the call to
dev_err would actually call to pch_console_write then we'll run into
another spin_lock(&priv->lock), with interrupts disabled.
So in the call sequence lead by pch_uart_interrupt, we should be
carefully to call functions that will 'print message to console' only
in case the uart port is not being used as serial console.
Signed-off-by: Liang Li <liang.li@windriver.com>
---
drivers/tty/serial/pch_uart.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 7d47514..2e99f79 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1034,22 +1034,37 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
{
u8 fcr = ioread8(priv->membase + UART_FCR);
+ struct uart_port *port = &priv->port;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+ char *error_msg[5] = {};
+ int i = 0;
/* Reset FIFO */
fcr |= UART_FCR_CLEAR_RCVR;
iowrite8(fcr, priv->membase + UART_FCR);
if (lsr & PCH_UART_LSR_ERR)
- dev_err(&priv->pdev->dev, "Error data in FIFO\n");
+ error_msg[i++] = "Error data in FIFO\n";
- if (lsr & UART_LSR_FE)
- dev_err(&priv->pdev->dev, "Framing Error\n");
+ if (lsr & UART_LSR_FE) {
+ port->icount.frame++;
+ error_msg[i++] = " Framing Error\n";
+ }
- if (lsr & UART_LSR_PE)
- dev_err(&priv->pdev->dev, "Parity Error\n");
+ if (lsr & UART_LSR_PE) {
+ port->icount.parity++;
+ error_msg[i++] = " Parity Error\n";
+ }
- if (lsr & UART_LSR_OE)
- dev_err(&priv->pdev->dev, "Overrun Error\n");
+ if (lsr & UART_LSR_OE) {
+ port->icount.overrun++;
+ error_msg[i++] = " Overrun Error\n";
+ }
+
+ if (tty == NULL) {
+ for (i = 0; error_msg[i] != NULL; i++)
+ dev_err(&priv->pdev->dev, error_msg[i]);
+ }
}
static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] pch_uart: add sysrq support
2013-01-19 9:52 [PATCH 0/2] pch_uart: fix a deadlock and add sysrq support Liang Li
2013-01-19 9:52 ` [PATCH 1/2] pch_uart: fix a deadlock when pch_uart as console Liang Li
@ 2013-01-19 9:52 ` Liang Li
1 sibling, 0 replies; 3+ messages in thread
From: Liang Li @ 2013-01-19 9:52 UTC (permalink / raw)
To: linux-serial, linux-kernel
Cc: liang.li, dvhart, bruce.ashfield, tomoya.rohm, feng.tang, alan,
gregkh
When send break to the uart port, we always get 'frame error', but we
can not just reset receive fifo in such case, otherwise the sysrq cmd
will not be received correctly.
When we handle sysrq output via pch_console_write, the priv lock has
already been taken so no need to take the lock in pch_console_write.
Signed-off-by: Liang Li <liang.li@windriver.com>
---
drivers/tty/serial/pch_uart.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 2e99f79..f2d67df 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -14,18 +14,21 @@
*along with this program; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
+#if defined(CONFIG_SERIAL_PCH_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
#include <linux/kernel.h>
#include <linux/serial_reg.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/dmi.h>
-#include <linux/console.h>
#include <linux/nmi.h>
#include <linux/delay.h>
@@ -552,12 +555,24 @@ static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
{
int i;
u8 rbr, lsr;
+ struct uart_port *port = &priv->port;
lsr = ioread8(priv->membase + UART_LSR);
for (i = 0, lsr = ioread8(priv->membase + UART_LSR);
- i < rx_size && lsr & UART_LSR_DR;
+ i < rx_size && lsr & (UART_LSR_DR | UART_LSR_BI);
lsr = ioread8(priv->membase + UART_LSR)) {
rbr = ioread8(priv->membase + PCH_UART_RBR);
+
+ if (lsr & UART_LSR_BI) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ }
+ if (port->sysrq) {
+ if (uart_handle_sysrq_char(port, rbr))
+ continue;
+ }
+
buf[i++] = rbr;
}
return i;
@@ -1033,16 +1048,11 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
{
- u8 fcr = ioread8(priv->membase + UART_FCR);
struct uart_port *port = &priv->port;
struct tty_struct *tty = tty_port_tty_get(&port->state->port);
char *error_msg[5] = {};
int i = 0;
- /* Reset FIFO */
- fcr |= UART_FCR_CLEAR_RCVR;
- iowrite8(fcr, priv->membase + UART_FCR);
-
if (lsr & PCH_UART_LSR_ERR)
error_msg[i++] = "Error data in FIFO\n";
@@ -1568,7 +1578,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
local_irq_save(flags);
if (priv->port.sysrq) {
- spin_lock(&priv->lock);
+ /* call to uart_handle_sysrq_char already took the priv lock */
+ priv_locked = 0;
/* serial8250_handle_port() already took the port lock */
port_locked = 0;
} else if (oops_in_progress) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-01-19 9:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-19 9:52 [PATCH 0/2] pch_uart: fix a deadlock and add sysrq support Liang Li
2013-01-19 9:52 ` [PATCH 1/2] pch_uart: fix a deadlock when pch_uart as console Liang Li
2013-01-19 9:52 ` [PATCH 2/2] pch_uart: add sysrq support Liang Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).