mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 02:01:29 +00:00
[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>
This commit is contained in:
parent
3ee68c4af3
commit
f91a3715db
@ -2164,7 +2164,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static inline void wait_for_xmitr(struct uart_8250_port *up)
|
||||
static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
@ -2178,7 +2178,7 @@ static inline void wait_for_xmitr(struct uart_8250_port *up)
|
||||
if (--tmout == 0)
|
||||
break;
|
||||
udelay(1);
|
||||
} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
|
||||
} while ((status & bits) != bits);
|
||||
|
||||
/* Wait up to 1s for flow control if necessary */
|
||||
if (up->port.flags & UPF_CONS_FLOW) {
|
||||
@ -2218,7 +2218,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++, s++) {
|
||||
wait_for_xmitr(up);
|
||||
wait_for_xmitr(up, UART_LSR_THRE);
|
||||
|
||||
/*
|
||||
* Send the character out.
|
||||
@ -2226,7 +2226,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
|
||||
*/
|
||||
serial_out(up, UART_TX, *s);
|
||||
if (*s == 10) {
|
||||
wait_for_xmitr(up);
|
||||
wait_for_xmitr(up, UART_LSR_THRE);
|
||||
serial_out(up, UART_TX, 13);
|
||||
}
|
||||
}
|
||||
@ -2235,8 +2235,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the IER
|
||||
*/
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_IER, ier);
|
||||
wait_for_xmitr(up, BOTH_EMPTY);
|
||||
serial_out(up, UART_IER, ier | UART_IER_THRI);
|
||||
}
|
||||
|
||||
static int serial8250_console_setup(struct console *co, char *options)
|
||||
|
Loading…
Reference in New Issue
Block a user