From: henz <patrick.h...@hpe.com> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2948
Timeouts in the XhciDxe driver are taking longer than expected due to the timeout loops not accounting for code execution time. As en example, 5 second timeouts have been observed to take around 36 seconds to complete. Use SetTimer and Create/CheckEvent from Boot Services to determine when timeout occurred. Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Hao A Wu <hao.a...@intel.com> Cc: Ray Ni <ray...@intel.com> Signed-off-by: Patrick Henz <patrick.h...@hpe.com> --- MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c | 28 ++++++++++++++++--- MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 34 +++++++++++++++++------- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c index 42b773ab31..5f7507f0a5 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c @@ -442,17 +442,37 @@ XhcWaitOpRegBit ( IN UINT32 Timeout ) { - UINT32 Index; - UINT64 Loop; + EFI_STATUS Status; + EFI_EVENT TimeoutEvent; - Loop = Timeout * XHC_1_MILLISECOND; + if (Timeout == 0) { + return EFI_TIMEOUT; + } + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); - for (Index = 0; Index < Loop; Index++) { + if (!EFI_ERROR (Status)) { + Status = gBS->SetTimer (TimeoutEvent, + TimerRelative, + EFI_TIMER_PERIOD_MILLISECONDS(Timeout)); + } + + do { if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) { return EFI_SUCCESS; } gBS->Stall (XHC_1_MICROSECOND); + } while (!EFI_ERROR(Status) && EFI_ERROR(gBS->CheckEvent (TimeoutEvent))); + + if (TimeoutEvent != NULL) { + gBS->CloseEvent (TimeoutEvent); } return EFI_TIMEOUT; diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c index ab8957c546..cf271f0493 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c @@ -1273,11 +1273,11 @@ XhcExecTransfer ( ) { EFI_STATUS Status; - UINTN Index; - UINT64 Loop; UINT8 SlotId; UINT8 Dci; BOOLEAN Finished; + EFI_EVENT TimeoutEvent; + EFI_STATUS TimerStatus; if (CmdTransfer) { SlotId = 0; @@ -1292,28 +1292,44 @@ XhcExecTransfer ( } Status = EFI_SUCCESS; - Loop = Timeout * XHC_1_MILLISECOND; - if (Timeout == 0) { - Loop = 0xFFFFFFFF; - } + + TimerStatus = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); XhcRingDoorBell (Xhc, SlotId, Dci); - for (Index = 0; Index < Loop; Index++) { + if (!EFI_ERROR (TimerStatus)) { + TimerStatus = gBS->SetTimer (TimeoutEvent, + TimerRelative, + (0 == Timeout)? + (EFI_TIMER_PERIOD_MICROSECONDS(0xFFFFFFFF)): + (EFI_TIMER_PERIOD_MILLISECONDS(Timeout))); + } + + do { Finished = XhcCheckUrbResult (Xhc, Urb); if (Finished) { break; } gBS->Stall (XHC_1_MICROSECOND); - } + } while (!EFI_ERROR(TimerStatus) && EFI_ERROR(gBS->CheckEvent (TimeoutEvent))); - if (Index == Loop) { + if (!Finished) { Urb->Result = EFI_USB_ERR_TIMEOUT; Status = EFI_TIMEOUT; } else if (Urb->Result != EFI_USB_NOERROR) { Status = EFI_DEVICE_ERROR; } + if (TimeoutEvent != NULL) { + gBS->CloseEvent (TimeoutEvent); + } + return Status; } -- 2.27.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#64945): https://edk2.groups.io/g/devel/message/64945 Mute This Topic: https://groups.io/mt/76577402/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-