git: 39d6144dcd94 - main - ns8250_drain: Drain without DELAY first
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 08 Oct 2022 00:56:31 UTC
The branch main has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=39d6144dcd94e9d07f07cb554aecb1f2d4089f6d commit 39d6144dcd94e9d07f07cb554aecb1f2d4089f6d Author: Colin Percival <cperciva@FreeBSD.org> AuthorDate: 2022-08-12 23:45:17 +0000 Commit: Colin Percival <cperciva@FreeBSD.org> CommitDate: 2022-10-08 00:51:54 +0000 ns8250_drain: Drain without DELAY first In virtual machines with virtual UARTs which have fictitious baud rates, it may be possible to drain the receive queue very quickly, without needing to DELAY after each character. Attempt to read (and discard) the receive queue as fast as possible, stopping for a DELAY only when LSR_RXRDY is no longer asserted; assume that we have finished draining the queue when LSR_RXRDY is asserted both before and after a DELAY. This speeds up the boot process in FreeBSD/Firecracker by 27 ms. Reviewed by: imp, jrtc27 Sponsored by: https://www.patreon.com/cperciva Differential Revision: https://reviews.freebsd.org/D36184 --- sys/dev/uart/uart_dev_ns8250.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index ada60b62b633..182831da7611 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -178,11 +178,18 @@ ns8250_drain(struct uart_bas *bas, int what) * limit high enough to handle large FIFOs and integrated * UARTs. The HP rx2600 for example has 3 UARTs on the * management board that tend to get a lot of data send - * to it when the UART is first activated. + * to it when the UART is first activated. Assume that we + * have finished draining if LSR_RXRDY is not asserted both + * prior to and after a DELAY; but as long as LSR_RXRDY is + * asserted, read (and discard) characters as quickly as + * possible. */ limit=10*4096; - while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) { - (void)uart_getreg(bas, REG_DATA); + while (limit && (uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) { + do { + (void)uart_getreg(bas, REG_DATA); + uart_barrier(bas); + } while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit); uart_barrier(bas); DELAY(delay << 2); }