mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/2] serial: samsung: Restore IRQ mask during noirq resume
@ 2013-03-27 23:34 Michael Spang
  2013-03-27 23:34 ` [PATCH 2/2] serial: samsung: Avoid waiting forever for TX ready Michael Spang
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Spang @ 2013-03-27 23:34 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel; +Cc: linux-serial, Michael Spang

This closes a window where the system may hang in resume as soon as the
UART interrupt is enabled and before the mask is restored. The hang occurs
because the driver can't handle IRQs it thinks are masked.

Signed-off-by: Michael Spang <spang@chromium.org>
---
 drivers/tty/serial/samsung.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 2769a38..161a7a0 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1307,9 +1307,29 @@ static int s3c24xx_serial_resume(struct device *dev)
 	return 0;
 }
 
+static int s3c24xx_serial_resume_noirq(struct device *dev)
+{
+	struct uart_port *port = s3c24xx_dev_to_port(dev);
+
+	if (port) {
+		/* restore IRQ mask */
+		if (s3c24xx_serial_has_interrupt_mask(port)) {
+			unsigned int uintm = 0xf;
+			if (tx_enabled(port))
+				uintm &= ~S3C64XX_UINTM_TXD_MSK;
+			if (rx_enabled(port))
+				uintm &= ~S3C64XX_UINTM_RXD_MSK;
+			wr_regl(port, S3C64XX_UINTM, uintm);
+		}
+	}
+
+	return 0;
+}
+
 static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
 	.suspend = s3c24xx_serial_suspend,
 	.resume = s3c24xx_serial_resume,
+	.resume_noirq = s3c24xx_serial_resume_noirq,
 };
 #define SERIAL_SAMSUNG_PM_OPS	(&s3c24xx_serial_pm_ops)
 
-- 
1.8.1.3


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 2/2] serial: samsung: Avoid waiting forever for TX ready
  2013-03-27 23:34 [PATCH 1/2] serial: samsung: Restore IRQ mask during noirq resume Michael Spang
@ 2013-03-27 23:34 ` Michael Spang
  0 siblings, 0 replies; 2+ messages in thread
From: Michael Spang @ 2013-03-27 23:34 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel; +Cc: linux-serial, Michael Spang

The no_console_suspend option allows the console to write to the UART
during early resume, before the serial port itself is resumed. Such
writes hang indefinitely waiting for TX ready.

This adds a check to the console putchar function to drop characters
instead of hanging if the port hasn't been initialized. That way, we
can use no_console_suspend without risk of hanging.

Signed-off-by: Michael Spang <spang@chromium.org>
---
 drivers/tty/serial/samsung.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 161a7a0..ca04901 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1363,6 +1363,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
 	return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
 }
 
+static bool
+s3c24xx_port_configured(unsigned int ucon)
+{
+	/* consider the serial port configured if the tx/rx mode set */
+	return (ucon & 0xf) != 0;
+}
+
 #ifdef CONFIG_CONSOLE_POLL
 /*
  * Console polling routines for writing and reading from the uart while
@@ -1385,6 +1392,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
 		unsigned char c)
 {
 	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+	unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+	/* not possible to xmit on unconfigured port */
+	if (!s3c24xx_port_configured(ucon))
+		return;
 
 	while (!s3c24xx_serial_console_txrdy(port, ufcon))
 		cpu_relax();
@@ -1397,6 +1409,12 @@ static void
 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
 {
 	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+	unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+	/* not possible to xmit on unconfigured port */
+	if (!s3c24xx_port_configured(ucon))
+		return;
+
 	while (!s3c24xx_serial_console_txrdy(port, ufcon))
 		barrier();
 	wr_regb(cons_uart, S3C2410_UTXH, ch);
@@ -1429,9 +1447,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
 	    "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
 	    port, ulcon, ucon, ubrdiv);
 
-	if ((ucon & 0xf) != 0) {
-		/* consider the serial port configured if the tx/rx mode set */
-
+	if (s3c24xx_port_configured(ucon)) {
 		switch (ulcon & S3C2410_LCON_CSMASK) {
 		case S3C2410_LCON_CS5:
 			*bits = 5;
-- 
1.8.1.3


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-03-27 23:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-27 23:34 [PATCH 1/2] serial: samsung: Restore IRQ mask during noirq resume Michael Spang
2013-03-27 23:34 ` [PATCH 2/2] serial: samsung: Avoid waiting forever for TX ready Michael Spang

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®