aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-16 02:53:32 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-16 07:05:28 -0400
commitf3c681c028846bd5d39f563909409832a295ca69 (patch)
treeff492b31f535a76f1d8ad82b916bb6293f550123
parent9918cc2e3275bf7f3561e4de1d5a3314183e71dc (diff)
[SERIAL]: Fix console write locking in sparc drivers.
Mirror the logic in 8250 for proper console write locking when SYSRQ is triggered or an OOPS is in progress. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/serial/sunhv.c30
-rw-r--r--drivers/serial/sunsab.c19
-rw-r--r--drivers/serial/sunsu.c14
-rw-r--r--drivers/serial/sunzilog.c17
4 files changed, 68 insertions, 12 deletions
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 96557e6dba60..17bcca53d6a1 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -440,8 +440,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
440{ 440{
441 struct uart_port *port = sunhv_port; 441 struct uart_port *port = sunhv_port;
442 unsigned long flags; 442 unsigned long flags;
443 int locked = 1;
444
445 local_irq_save(flags);
446 if (port->sysrq) {
447 locked = 0;
448 } else if (oops_in_progress) {
449 locked = spin_trylock(&port->lock);
450 } else
451 spin_lock(&port->lock);
443 452
444 spin_lock_irqsave(&port->lock, flags);
445 while (n > 0) { 453 while (n > 0) {
446 unsigned long ra = __pa(con_write_page); 454 unsigned long ra = __pa(con_write_page);
447 unsigned long page_bytes; 455 unsigned long page_bytes;
@@ -469,7 +477,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
469 ra += written; 477 ra += written;
470 } 478 }
471 } 479 }
472 spin_unlock_irqrestore(&port->lock, flags); 480
481 if (locked)
482 spin_unlock(&port->lock);
483 local_irq_restore(flags);
473} 484}
474 485
475static inline void sunhv_console_putchar(struct uart_port *port, char c) 486static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
488{ 499{
489 struct uart_port *port = sunhv_port; 500 struct uart_port *port = sunhv_port;
490 unsigned long flags; 501 unsigned long flags;
491 int i; 502 int i, locked = 1;
503
504 local_irq_save(flags);
505 if (port->sysrq) {
506 locked = 0;
507 } else if (oops_in_progress) {
508 locked = spin_trylock(&port->lock);
509 } else
510 spin_lock(&port->lock);
492 511
493 spin_lock_irqsave(&port->lock, flags); 512 spin_lock_irqsave(&port->lock, flags);
494 for (i = 0; i < n; i++) { 513 for (i = 0; i < n; i++) {
@@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
496 sunhv_console_putchar(port, '\r'); 515 sunhv_console_putchar(port, '\r');
497 sunhv_console_putchar(port, *s++); 516 sunhv_console_putchar(port, *s++);
498 } 517 }
499 spin_unlock_irqrestore(&port->lock, flags); 518
519 if (locked)
520 spin_unlock(&port->lock);
521 local_irq_restore(flags);
500} 522}
501 523
502static struct console sunhv_console = { 524static struct console sunhv_console = {
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index deb9ab4b5a0b..8a0f9e4408d4 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -860,22 +860,31 @@ static int num_channels;
860static void sunsab_console_putchar(struct uart_port *port, int c) 860static void sunsab_console_putchar(struct uart_port *port, int c)
861{ 861{
862 struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; 862 struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
863 unsigned long flags;
864
865 spin_lock_irqsave(&up->port.lock, flags);
866 863
867 sunsab_tec_wait(up); 864 sunsab_tec_wait(up);
868 writeb(c, &up->regs->w.tic); 865 writeb(c, &up->regs->w.tic);
869
870 spin_unlock_irqrestore(&up->port.lock, flags);
871} 866}
872 867
873static void sunsab_console_write(struct console *con, const char *s, unsigned n) 868static void sunsab_console_write(struct console *con, const char *s, unsigned n)
874{ 869{
875 struct uart_sunsab_port *up = &sunsab_ports[con->index]; 870 struct uart_sunsab_port *up = &sunsab_ports[con->index];
871 unsigned long flags;
872 int locked = 1;
873
874 local_irq_save(flags);
875 if (up->port.sysrq) {
876 locked = 0;
877 } else if (oops_in_progress) {
878 locked = spin_trylock(&up->port.lock);
879 } else
880 spin_lock(&up->port.lock);
876 881
877 uart_console_write(&up->port, s, n, sunsab_console_putchar); 882 uart_console_write(&up->port, s, n, sunsab_console_putchar);
878 sunsab_tec_wait(up); 883 sunsab_tec_wait(up);
884
885 if (locked)
886 spin_unlock(&up->port.lock);
887 local_irq_restore(flags);
879} 888}
880 889
881static int sunsab_console_setup(struct console *con, char *options) 890static int sunsab_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2a63cdba3208..26d720baf88c 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s,
1288 unsigned int count) 1288 unsigned int count)
1289{ 1289{
1290 struct uart_sunsu_port *up = &sunsu_ports[co->index]; 1290 struct uart_sunsu_port *up = &sunsu_ports[co->index];
1291 unsigned long flags;
1291 unsigned int ier; 1292 unsigned int ier;
1293 int locked = 1;
1294
1295 local_irq_save(flags);
1296 if (up->port.sysrq) {
1297 locked = 0;
1298 } else if (oops_in_progress) {
1299 locked = spin_trylock(&up->port.lock);
1300 } else
1301 spin_lock(&up->port.lock);
1292 1302
1293 /* 1303 /*
1294 * First save the UER then disable the interrupts 1304 * First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s,
1304 */ 1314 */
1305 wait_for_xmitr(up); 1315 wait_for_xmitr(up);
1306 serial_out(up, UART_IER, ier); 1316 serial_out(up, UART_IER, ier);
1317
1318 if (locked)
1319 spin_unlock(&up->port.lock);
1320 local_irq_restore(flags);
1307} 1321}
1308 1322
1309/* 1323/*
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 15b6e1cb040b..0a3e10a4a35d 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -9,7 +9,7 @@
9 * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their 9 * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
10 * work there. 10 * work there.
11 * 11 *
12 * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net) 12 * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
13 */ 13 */
14 14
15#include <linux/module.h> 15#include <linux/module.h>
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
1151{ 1151{
1152 struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; 1152 struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
1153 unsigned long flags; 1153 unsigned long flags;
1154 int locked = 1;
1155
1156 local_irq_save(flags);
1157 if (up->port.sysrq) {
1158 locked = 0;
1159 } else if (oops_in_progress) {
1160 locked = spin_trylock(&up->port.lock);
1161 } else
1162 spin_lock(&up->port.lock);
1154 1163
1155 spin_lock_irqsave(&up->port.lock, flags);
1156 uart_console_write(&up->port, s, count, sunzilog_putchar); 1164 uart_console_write(&up->port, s, count, sunzilog_putchar);
1157 udelay(2); 1165 udelay(2);
1158 spin_unlock_irqrestore(&up->port.lock, flags); 1166
1167 if (locked)
1168 spin_unlock(&up->port.lock);
1169 local_irq_restore(flags);
1159} 1170}
1160 1171
1161static int __init sunzilog_console_setup(struct console *con, char *options) 1172static int __init sunzilog_console_setup(struct console *con, char *options)