aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/samsung.c
diff options
context:
space:
mode:
authorMichael Spang <spang@chromium.org>2013-03-27 19:34:25 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-28 19:04:19 -0400
commit38adbc54cea90e220c9212f961a621b2c6af9ae0 (patch)
treea9f87cf017db71038715f15e277d3a6f687a280d /drivers/tty/serial/samsung.c
parentd09a7308e9887a83abfd3176f4416d4142a265dc (diff)
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: Michael Spang <spang@chromium.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/samsung.c')
-rw-r--r--drivers/tty/serial/samsung.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 78d9c55a9f84..7883f11b8c53 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1367,6 +1367,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1367 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; 1367 return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
1368} 1368}
1369 1369
1370static bool
1371s3c24xx_port_configured(unsigned int ucon)
1372{
1373 /* consider the serial port configured if the tx/rx mode set */
1374 return (ucon & 0xf) != 0;
1375}
1376
1370#ifdef CONFIG_CONSOLE_POLL 1377#ifdef CONFIG_CONSOLE_POLL
1371/* 1378/*
1372 * Console polling routines for writing and reading from the uart while 1379 * 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 unsigned char c) 1396 unsigned char c)
1390{ 1397{
1391 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 1398 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
1399 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
1400
1401 /* not possible to xmit on unconfigured port */
1402 if (!s3c24xx_port_configured(ucon))
1403 return;
1392 1404
1393 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1405 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1394 cpu_relax(); 1406 cpu_relax();
@@ -1401,6 +1413,12 @@ static void
1401s3c24xx_serial_console_putchar(struct uart_port *port, int ch) 1413s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1402{ 1414{
1403 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); 1415 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
1416 unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
1417
1418 /* not possible to xmit on unconfigured port */
1419 if (!s3c24xx_port_configured(ucon))
1420 return;
1421
1404 while (!s3c24xx_serial_console_txrdy(port, ufcon)) 1422 while (!s3c24xx_serial_console_txrdy(port, ufcon))
1405 barrier(); 1423 barrier();
1406 wr_regb(cons_uart, S3C2410_UTXH, ch); 1424 wr_regb(cons_uart, S3C2410_UTXH, ch);
@@ -1433,9 +1451,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
1433 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", 1451 "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1434 port, ulcon, ucon, ubrdiv); 1452 port, ulcon, ucon, ubrdiv);
1435 1453
1436 if ((ucon & 0xf) != 0) { 1454 if (s3c24xx_port_configured(ucon)) {
1437 /* consider the serial port configured if the tx/rx mode set */
1438
1439 switch (ulcon & S3C2410_LCON_CSMASK) { 1455 switch (ulcon & S3C2410_LCON_CSMASK) {
1440 case S3C2410_LCON_CS5: 1456 case S3C2410_LCON_CS5:
1441 *bits = 5; 1457 *bits = 5;