提交 38adbc54 编写于 作者: M Michael Spang 提交者: Greg Kroah-Hartman

serial: samsung: Avoid waiting forever for TX ready

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: NMichael Spang <spang@chromium.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 d09a7308
...@@ -1367,6 +1367,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) ...@@ -1367,6 +1367,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; 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 #ifdef CONFIG_CONSOLE_POLL
/* /*
* Console polling routines for writing and reading from the uart while * Console polling routines for writing and reading from the uart while
...@@ -1389,6 +1396,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, ...@@ -1389,6 +1396,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c) unsigned char c)
{ {
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 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)) while (!s3c24xx_serial_console_txrdy(port, ufcon))
cpu_relax(); cpu_relax();
...@@ -1401,6 +1413,12 @@ static void ...@@ -1401,6 +1413,12 @@ static void
s3c24xx_serial_console_putchar(struct uart_port *port, int ch) s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
{ {
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 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)) while (!s3c24xx_serial_console_txrdy(port, ufcon))
barrier(); barrier();
wr_regb(cons_uart, S3C2410_UTXH, ch); wr_regb(cons_uart, S3C2410_UTXH, ch);
...@@ -1433,9 +1451,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, ...@@ -1433,9 +1451,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
"registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
port, ulcon, ucon, ubrdiv); port, ulcon, ucon, ubrdiv);
if ((ucon & 0xf) != 0) { if (s3c24xx_port_configured(ucon)) {
/* consider the serial port configured if the tx/rx mode set */
switch (ulcon & S3C2410_LCON_CSMASK) { switch (ulcon & S3C2410_LCON_CSMASK) {
case S3C2410_LCON_CS5: case S3C2410_LCON_CS5:
*bits = 5; *bits = 5;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册