diff options
author | Michael Spang <spang@chromium.org> | 2013-03-27 19:34:25 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-28 19:04:19 -0400 |
commit | 38adbc54cea90e220c9212f961a621b2c6af9ae0 (patch) | |
tree | a9f87cf017db71038715f15e277d3a6f687a280d /drivers/tty/serial/samsung.c | |
parent | d09a7308e9887a83abfd3176f4416d4142a265dc (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.c | 22 |
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 | ||
1370 | static bool | ||
1371 | s3c24xx_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 | |||
1401 | s3c24xx_serial_console_putchar(struct uart_port *port, int ch) | 1413 | s3c24xx_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; |