From: Eric Curtin <ericcurtin17@gmail.com>
To: Russell King <linux@armlinux.org.uk>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jirislaby@kernel.org>
Cc: Eric Curtin <ericcurtin17@gmail.com>,
linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] serial: amba-pl011: drop redundant BUSY wait from earlycon pl011_putc()
Date: Fri, 3 Jul 2026 19:16:36 +0000 [thread overview]
Message-ID: <20260703191638.131476-1-ericcurtin17@gmail.com> (raw)
pl011_putc(), used exclusively by the pl011 earlycon (pl011_early_write()
-> uart_console_write()), waits for UART01x_FR_TXFF to clear before
writing a character (correct: don't overrun the TX FIFO) and then *also*
busy-waits for UART01x_FR_BUSY to clear before returning, i.e. it waits
for the character to be fully shifted out on the wire before the next
character in the string can even be considered.
This second wait is not required for correctness and is inconsistent
with the rest of this same driver: both pl011_console_putchar() (the
regular, always-built console write path used by every printk() once
the full driver is up) and pl011_put_poll_char() (kgdb/kdb polling I/O)
only wait for TXFF before writing and never wait for BUSY afterwards.
pl011_putc() is the only one of the three that serializes on BUSY, and
it is the one exercised the most heavily, since it backs earlycon and
therefore every line printed during early boot before the real console
takes over.
Waiting for BUSY defeats the TX FIFO: instead of letting the UART
buffer several queued bytes and transmit them back to back, every
single character printed through earlycon is forced to wait for that
character's own complete transmission (a full UART bit-time at the
configured baud rate) before the driver will even look at writing the
next one. This is wasted time on real hardware, and it is much worse
under virtualization: each read of UARTFR and each write to UARTDR is
an MMIO access that traps to the hypervisor, so removing the extra
poll removes one entire VM-exit/entry round trip per character printed
through earlycon.
This is easy to see, and to prove, in a fast-booting VMM. Using a small
KVM-based VMM that boots Linux guests directly on arm64 (no firmware),
booting an otherwise-identical 7.2.0-rc1 kernel (single vCPU, 512MB
guest, direct PL011 MMIO with no interrupt-driven UART - i.e. earlycon
is the only console active) up to the (expected, rootfs-less)
"Unable to mount root fs" panic, with 20 boot samples per kernel per
configuration:
cmdline: console=ttyAMA0 earlycon=pl011,0x09000000 ignore_loglevel
initcall_debug printk.time=1 (~99KB printed over earlycon)
before: min 466.3ms avg 471.4ms max 480.3ms (n=20)
after: min 429.5ms avg 433.3ms max 442.6ms (n=19)
-> ~38ms / ~8% faster, non-overlapping distributions
cmdline: <the VMM's actual default, quiet, earlycon=pl011,0x09000000>
before: min 74.3ms avg 76.5ms max 82.2ms (n=20)
after: min 53.6ms avg 55.4ms max 60.7ms (n=20)
-> ~21ms / ~28% faster, non-overlapping distributions
The second measurement uses the VMM's real default boot configuration
(not a synthetic debug cmdline), so this is representative of ordinary
boots, not just verbose-logging ones. Console content was diffed
(timestamps and per-initcall "returned 0 after N usecs" numbers
excluded) between before/after runs and is byte-for-byte identical
line-for-line: this change is a pure removal of unnecessary polling,
with no functional or ordering change.
Signed-off-by: Eric Curtin <ericcurtin17@gmail.com>
---
drivers/tty/serial/amba-pl011.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 8ed91e1da22be..2a25095e8d8c7 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2741,8 +2741,6 @@ static void pl011_putc(struct uart_port *port, unsigned char c)
writel(c, port->membase + UART01x_DR);
else
writeb(c, port->membase + UART01x_DR);
- while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
- cpu_relax();
}
static void pl011_early_write(struct console *con, const char *s, unsigned int n)
--
2.54.0
next reply other threads:[~2026-07-03 19:17 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 19:16 Eric Curtin [this message]
2026-07-03 19:38 ` [PATCH v2] serial: amba-pl011: don't wait for BUSY after every earlycon character Eric Curtin
2026-07-10 12:38 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703191638.131476-1-ericcurtin17@gmail.com \
--to=ericcurtin17@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=linux@armlinux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox