|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 2/2] xen/ns16550: drain TX before reinitializing the UART
Drain pending output before resetting FIFOs. Bound the wait to avoid
hanging boot if the UART never reports empty.
Wait for TEMT (which already implies THRE on a 16550) to ensure
transmission has finished before reconfiguration. uart->lsr_mask normally
checks only THRE, which indicates room for more output.
Signed-off-by: Zhang Zheng <zhangzheng@xxxxxxxxxxx>
---
xen/drivers/char/ns16550.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 1f54155d67..29f784280e 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -410,6 +410,12 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
static void __init cf_check ns16550_init_preirq(struct serial_port *port)
{
struct ns16550 *uart = port->uart;
+ cycles_t start;
+ /*
+ * Too early for proper time calibration, assume a 5GHz CPU and let it wait
+ * about 1s, with still reasonable timeout on a slower CPU.
+ */
+ cycles_t timeout_ticks = 5UL * 1000 * 1000 * 1000;
#ifdef CONFIG_HAS_IOPORTS
/* I/O ports are distinguished by their size (16 bits). */
@@ -427,6 +433,15 @@ static void __init cf_check ns16550_init_preirq(struct
serial_port *port)
#endif
}
+ /*
+ * Drain firmware/early-console output before changing line settings or
+ * resetting FIFOs. Wait for TEMT so the shift register is empty too.
+ */
+ start = get_cycles();
+ while ( !(ns_read_reg(uart, UART_LSR) & UART_LSR_TEMT) &&
+ get_cycles() - start < timeout_ticks )
+ cpu_relax();
+
ns16550_setup_preirq(uart);
/* Check this really is a 16550+. Otherwise we have no FIFOs. */
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |