Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Alan Cox and committed by
Russell King
f91a3715 3ee68c4a

+6 -6
+6 -6
drivers/serial/8250.c
··· 2164 2164 /* 2165 2165 * Wait for transmitter & holding register to empty 2166 2166 */ 2167 - static inline void wait_for_xmitr(struct uart_8250_port *up) 2167 + static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) 2168 2168 { 2169 2169 unsigned int status, tmout = 10000; 2170 2170 ··· 2178 2178 if (--tmout == 0) 2179 2179 break; 2180 2180 udelay(1); 2181 - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); 2181 + } while ((status & bits) != bits); 2182 2182 2183 2183 /* Wait up to 1s for flow control if necessary */ 2184 2184 if (up->port.flags & UPF_CONS_FLOW) { ··· 2218 2218 * Now, do each character 2219 2219 */ 2220 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 2224 * Send the character out. ··· 2226 2226 */ 2227 2227 serial_out(up, UART_TX, *s); 2228 2228 if (*s == 10) { 2229 - wait_for_xmitr(up); 2229 + wait_for_xmitr(up, UART_LSR_THRE); 2230 2230 serial_out(up, UART_TX, 13); 2231 2231 } 2232 2232 } ··· 2235 2235 * Finally, wait for transmitter to become empty 2236 2236 * and restore the IER 2237 2237 */ 2238 - wait_for_xmitr(up); 2239 - serial_out(up, UART_IER, ier); 2238 + wait_for_xmitr(up, BOTH_EMPTY); 2239 + serial_out(up, UART_IER, ier | UART_IER_THRI); 2240 2240 } 2241 2241 2242 2242 static int serial8250_console_setup(struct console *co, char *options)