aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-01-21 09:59:12 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-21 09:59:12 -0500
commitf91a3715db2bb44fcf08cec642e68f919b70f7f4 (patch)
tree119d0917c2b9df55bf548e38ace5fcae8334f38e /drivers/serial
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
[SERIAL] 8250 serial console fixes
This patch resolves most of the problems with an SMP serial console race with output via the tty path. At the end of the serial console print we force enable the tx int in case we clobbered the tx interrupt status racing between the console and tty output. That way the extra tx interrupt causes the transmit path to restart not hang. It also makes the serial console printk use the FIFO. This is neccessary because some remote management devices fake serial console with FIFO and are confused into sending one packet per character over ethernet when we stall rather than filling the FIFO. In order to preserve existing reliability semantics the function waits for the serial queue to completely empty before returning. Both of these problems were identified by a Red Hat partner. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index bc36edff2058..ff2f931c6715 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2164,7 +2164,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
2164/* 2164/*
2165 * Wait for transmitter & holding register to empty 2165 * Wait for transmitter & holding register to empty
2166 */ 2166 */
2167static inline void wait_for_xmitr(struct uart_8250_port *up) 2167static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
2168{ 2168{
2169 unsigned int status, tmout = 10000; 2169 unsigned int status, tmout = 10000;
2170 2170
@@ -2178,7 +2178,7 @@ static inline void wait_for_xmitr(struct uart_8250_port *up)
2178 if (--tmout == 0) 2178 if (--tmout == 0)
2179 break; 2179 break;
2180 udelay(1); 2180 udelay(1);
2181 } while ((status & BOTH_EMPTY) != BOTH_EMPTY); 2181 } while ((status & bits) != bits);
2182 2182
2183 /* Wait up to 1s for flow control if necessary */ 2183 /* Wait up to 1s for flow control if necessary */
2184 if (up->port.flags & UPF_CONS_FLOW) { 2184 if (up->port.flags & UPF_CONS_FLOW) {
@@ -2218,7 +2218,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2218 * Now, do each character 2218 * Now, do each character
2219 */ 2219 */
2220 for (i = 0; i < count; i++, s++) { 2220 for (i = 0; i < count; i++, s++) {
2221 wait_for_xmitr(up); 2221 wait_for_xmitr(up, UART_LSR_THRE);
2222 2222
2223 /* 2223 /*
2224 * Send the character out. 2224 * Send the character out.
@@ -2226,7 +2226,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2226 */ 2226 */
2227 serial_out(up, UART_TX, *s); 2227 serial_out(up, UART_TX, *s);
2228 if (*s == 10) { 2228 if (*s == 10) {
2229 wait_for_xmitr(up); 2229 wait_for_xmitr(up, UART_LSR_THRE);
2230 serial_out(up, UART_TX, 13); 2230 serial_out(up, UART_TX, 13);
2231 } 2231 }
2232 } 2232 }
@@ -2235,8 +2235,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
2235 * Finally, wait for transmitter to become empty 2235 * Finally, wait for transmitter to become empty
2236 * and restore the IER 2236 * and restore the IER
2237 */ 2237 */
2238 wait_for_xmitr(up); 2238 wait_for_xmitr(up, BOTH_EMPTY);
2239 serial_out(up, UART_IER, ier); 2239 serial_out(up, UART_IER, ier | UART_IER_THRI);
2240} 2240}
2241 2241
2242static int serial8250_console_setup(struct console *co, char *options) 2242static int serial8250_console_setup(struct console *co, char *options)