efi: serial: Speed up reading from input

The serial driver is currently quite slow since it sets an event and
waits for at least 1ms for a keypress, which may never come.

On real hardware, the keyboard does not work correctly wihout waiting
for events. Reduce the time to 10us which should be enough to provide an
opportunity for event processing.

QEMU does not actually have this problem, so detect that and skip the
processing altogether.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-10-05 15:30:01 -06:00
parent 02fa448bcc
commit e5422499b5

View File

@@ -12,9 +12,12 @@
#include <fdtdec.h>
#include <log.h>
#include <linux/compiler.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
/* Information about the efi console */
struct serial_efi_priv {
struct efi_simple_text_input_protocol *con_in;
@@ -44,26 +47,38 @@ int serial_efi_setbrg(struct udevice *dev, int baudrate)
static int serial_efi_get_key(struct serial_efi_priv *priv)
{
struct efi_simple_text_input_protocol *cin = priv->con_in;
struct efi_event *events[2] = {cin->wait_for_key, priv->timer};
efi_uintn_t index;
efi_status_t ret;
if (priv->have_key)
return 0;
ret = priv->boot->wait_for_event(2, events, &index);
if (ret) {
log_err("wait_for_event() failed\n");
return -EAGAIN;
}
if (index)
return -EAGAIN;
/* For emulators like QEMU, skip the timer wait since USB event
* processing is not needed
*/
if (gd->flags & GD_FLG_EMUL) {
ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
if (ret == EFI_NOT_READY)
return -EAGAIN;
else if (ret != EFI_SUCCESS)
return -EIO;
} else {
struct efi_event *events[2] = {cin->wait_for_key, priv->timer};
efi_uintn_t index;
ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
if (ret == EFI_NOT_READY)
return -EAGAIN;
else if (ret != EFI_SUCCESS)
return -EIO;
ret = priv->boot->wait_for_event(2, events, &index);
if (ret) {
log_err("wait_for_event() failed\n");
return -EAGAIN;
}
if (index)
return -EAGAIN;
ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
if (ret == EFI_NOT_READY)
return -EAGAIN;
else if (ret != EFI_SUCCESS)
return -EIO;
}
priv->have_key = true;
@@ -155,7 +170,7 @@ static int serial_efi_probe(struct udevice *dev)
if (ret)
return -ECOMM;
ret = boot->set_timer(priv->timer, EFI_TIMER_PERIODIC,
1000 * 1000 / 100 /* 1ms in 100ns units */);
100 /* 1s in 100ns units */);
if (ret)
return -ECOMM;