public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v3 0/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
@ 2020-09-23 19:36 Henz, Patrick
  2020-09-23 19:36 ` [PATCH v3 1/1] " Henz, Patrick
  0 siblings, 1 reply; 7+ messages in thread
From: Henz, Patrick @ 2020-09-23 19:36 UTC (permalink / raw)
  To: devel; +Cc: Patrick Henz, Jian J Wang, Hao A Wu, Ray Ni

From: Patrick Henz <patrick.henz@hpe.com>

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. This patch was tested
using forced timeouts and print statements with QEmu as
well as phycial hardware. The forced timeouts were
implemented in code via static variables that guaranteed
a timeout the first time the function with the broken
timeout was called.

Example:

XhcExecTransfer (
  .
  .
 )
{
  .
  .
  static int do_once = 1;  // test line
  .
  .
  do {
    Finished = XhcCheckUrbResult (Xhc, Urb);
    if (do_once) Finished = 0; // test line
    if (Finished) {
      break;
    }
    gBS->Stall (XHC_1_MICROSECOND);
  } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));

  do_once = 0; // test line

Using this forced timeout approach the correct timeouts
were observed on both hardware and in QEmu.

Similar broken timeout loops have been found in the Uhci
and Ehci drivers. This patch does not fix those issues.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Patrick Henz <patrick.henz@hpe.com>

Patrick Henz (1):
  MdeModulePkg/XhciDxe: Fix Broken Timeouts

 MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c   | 59 +++++++++++++++++-----
 MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 63 ++++++++++++++++++------
 2 files changed, 94 insertions(+), 28 deletions(-)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2020-09-23 19:36 [PATCH v3 0/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts Henz, Patrick
@ 2020-09-23 19:36 ` Henz, Patrick
  2020-09-24  1:22   ` [edk2-devel] " Wu, Hao A
  2023-06-07 21:37   ` Jessica Clarke
  0 siblings, 2 replies; 7+ messages in thread
From: Henz, Patrick @ 2020-09-23 19:36 UTC (permalink / raw)
  To: devel; +Cc: Patrick Henz, Jian J Wang, Hao A Wu, Ray Ni

From: Patrick Henz <patrick.henz@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.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Patrick Henz <patrick.henz@hpe.com>
---
 MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c   | 59 +++++++++++++++++-----
 MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 63 ++++++++++++++++++------
 2 files changed, 94 insertions(+), 28 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index 42b773ab31be..2bab09415b28 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -423,14 +423,15 @@ XhcClearOpRegBit (
   Wait the operation register's bit as specified by Bit
   to become set (or clear).
 
-  @param  Xhc          The XHCI Instance.
-  @param  Offset       The offset of the operation register.
-  @param  Bit          The bit of the register to wait for.
-  @param  WaitToSet    Wait the bit to set or clear.
-  @param  Timeout      The time to wait before abort (in millisecond, ms).
+  @param  Xhc                    The XHCI Instance.
+  @param  Offset                 The offset of the operation register.
+  @param  Bit                    The bit of the register to wait for.
+  @param  WaitToSet              Wait the bit to set or clear.
+  @param  Timeout                The time to wait before abort (in millisecond, ms).
 
-  @retval EFI_SUCCESS  The bit successfully changed by host controller.
-  @retval EFI_TIMEOUT  The time out occurred.
+  @retval EFI_SUCCESS            The bit successfully changed by host controller.
+  @retval EFI_TIMEOUT            The time out occurred.
+  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could not be allocated.
 
 **/
 EFI_STATUS
@@ -442,20 +443,52 @@ XhcWaitOpRegBit (
   IN UINT32               Timeout
   )
 {
-  UINT32                  Index;
-  UINT64                  Loop;
+  EFI_STATUS Status;
+  EFI_EVENT  TimeoutEvent;
 
-  Loop   = Timeout * XHC_1_MILLISECOND;
+  TimeoutEvent = NULL;
 
-  for (Index = 0; Index < Loop; Index++) {
+  if (Timeout == 0) {
+    return EFI_TIMEOUT;
+  }
+
+  Status = gBS->CreateEvent (
+                  EVT_TIMER,
+                  TPL_CALLBACK,
+                  NULL,
+                  NULL,
+                  &TimeoutEvent
+                  );
+
+  if (EFI_ERROR(Status)) {
+    goto DONE;
+  }
+
+  Status = gBS->SetTimer (TimeoutEvent,
+                          TimerRelative,
+                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
+
+  if (EFI_ERROR(Status)) {
+    goto DONE;
+  }
+
+  do {
     if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
-      return EFI_SUCCESS;
+      Status = EFI_SUCCESS;
+      goto DONE;
     }
 
     gBS->Stall (XHC_1_MICROSECOND);
+  } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
+
+  Status = EFI_TIMEOUT;
+
+DONE:
+  if (TimeoutEvent != NULL) {
+    gBS->CloseEvent (TimeoutEvent);
   }
 
-  return EFI_TIMEOUT;
+  return Status;
 }
 
 /**
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index ab8957c546ee..9cb115363c8b 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -1254,14 +1254,15 @@ XhcCheckUrbResult (
 /**
   Execute the transfer by polling the URB. This is a synchronous operation.
 
-  @param  Xhc               The XHCI Instance.
-  @param  CmdTransfer       The executed URB is for cmd transfer or not.
-  @param  Urb               The URB to execute.
-  @param  Timeout           The time to wait before abort, in millisecond.
+  @param  Xhc                    The XHCI Instance.
+  @param  CmdTransfer            The executed URB is for cmd transfer or not.
+  @param  Urb                    The URB to execute.
+  @param  Timeout                The time to wait before abort, in millisecond.
 
-  @return EFI_DEVICE_ERROR  The transfer failed due to transfer error.
-  @return EFI_TIMEOUT       The transfer failed due to time out.
-  @return EFI_SUCCESS       The transfer finished OK.
+  @return EFI_DEVICE_ERROR       The transfer failed due to transfer error.
+  @return EFI_TIMEOUT            The transfer failed due to time out.
+  @return EFI_SUCCESS            The transfer finished OK.
+  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could not be allocated.
 
 **/
 EFI_STATUS
@@ -1273,11 +1274,16 @@ XhcExecTransfer (
   )
 {
   EFI_STATUS              Status;
-  UINTN                   Index;
-  UINT64                  Loop;
   UINT8                   SlotId;
   UINT8                   Dci;
   BOOLEAN                 Finished;
+  EFI_EVENT               TimeoutEvent;
+  BOOLEAN                 IndefiniteTimeout;
+
+  Status            = EFI_SUCCESS;
+  Finished          = FALSE;
+  TimeoutEvent      = NULL;
+  IndefiniteTimeout = FALSE;
 
   if (CmdTransfer) {
     SlotId = 0;
@@ -1291,29 +1297,56 @@ XhcExecTransfer (
     ASSERT (Dci < 32);
   }
 
-  Status = EFI_SUCCESS;
-  Loop   = Timeout * XHC_1_MILLISECOND;
   if (Timeout == 0) {
-    Loop = 0xFFFFFFFF;
+    IndefiniteTimeout = TRUE;
+    goto RINGDOORBELL;
   }
 
+  Status = gBS->CreateEvent (
+                  EVT_TIMER,
+                  TPL_CALLBACK,
+                  NULL,
+                  NULL,
+                  &TimeoutEvent
+                  );
+
+  if (EFI_ERROR (Status)) {
+    goto DONE;
+  }
+
+  Status = gBS->SetTimer (TimeoutEvent,
+                          TimerRelative,
+                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
+
+  if (EFI_ERROR (Status)) {
+    goto DONE;
+  }
+
+RINGDOORBELL:
   XhcRingDoorBell (Xhc, SlotId, Dci);
 
-  for (Index = 0; Index < Loop; Index++) {
+  do {
     Finished = XhcCheckUrbResult (Xhc, Urb);
     if (Finished) {
       break;
     }
     gBS->Stall (XHC_1_MICROSECOND);
-  }
+  } while (IndefiniteTimeout || EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
 
-  if (Index == Loop) {
+DONE:
+  if (EFI_ERROR(Status)) {
+    Urb->Result = EFI_USB_ERR_NOTEXECUTE;
+  } else 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.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2020-09-23 19:36 ` [PATCH v3 1/1] " Henz, Patrick
@ 2020-09-24  1:22   ` Wu, Hao A
  2020-09-29  1:31     ` Wu, Hao A
  2023-06-07 21:37   ` Jessica Clarke
  1 sibling, 1 reply; 7+ messages in thread
From: Wu, Hao A @ 2020-09-24  1:22 UTC (permalink / raw)
  To: devel@edk2.groups.io, patrick.henz@hpe.com; +Cc: Wang, Jian J, Ni, Ray

Reviewed-by: Hao A Wu <hao.a.wu@intel.com>

Best Regards,
Hao Wu

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Henz,
> Patrick
> Sent: Thursday, September 24, 2020 3:36 AM
> To: devel@edk2.groups.io
> Cc: Patrick Henz <patrick.henz@hpe.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray
> <ray.ni@intel.com>
> Subject: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken
> Timeouts
> 
> From: Patrick Henz <patrick.henz@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.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Patrick Henz <patrick.henz@hpe.com>
> ---
>  MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c   | 59 +++++++++++++++++-----
>  MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 63 ++++++++++++++++++--
> ----
>  2 files changed, 94 insertions(+), 28 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> index 42b773ab31be..2bab09415b28 100644
> --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> @@ -423,14 +423,15 @@ XhcClearOpRegBit (
>    Wait the operation register's bit as specified by Bit
>    to become set (or clear).
> 
> -  @param  Xhc          The XHCI Instance.
> -  @param  Offset       The offset of the operation register.
> -  @param  Bit          The bit of the register to wait for.
> -  @param  WaitToSet    Wait the bit to set or clear.
> -  @param  Timeout      The time to wait before abort (in millisecond, ms).
> +  @param  Xhc                    The XHCI Instance.
> +  @param  Offset                 The offset of the operation register.
> +  @param  Bit                    The bit of the register to wait for.
> +  @param  WaitToSet              Wait the bit to set or clear.
> +  @param  Timeout                The time to wait before abort (in millisecond,
> ms).
> 
> -  @retval EFI_SUCCESS  The bit successfully changed by host controller.
> -  @retval EFI_TIMEOUT  The time out occurred.
> +  @retval EFI_SUCCESS            The bit successfully changed by host controller.
> +  @retval EFI_TIMEOUT            The time out occurred.
> +  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could not
> be allocated.
> 
>  **/
>  EFI_STATUS
> @@ -442,20 +443,52 @@ XhcWaitOpRegBit (
>    IN UINT32               Timeout
>    )
>  {
> -  UINT32                  Index;
> -  UINT64                  Loop;
> +  EFI_STATUS Status;
> +  EFI_EVENT  TimeoutEvent;
> 
> -  Loop   = Timeout * XHC_1_MILLISECOND;
> +  TimeoutEvent = NULL;
> 
> -  for (Index = 0; Index < Loop; Index++) {
> +  if (Timeout == 0) {
> +    return EFI_TIMEOUT;
> +  }
> +
> +  Status = gBS->CreateEvent (
> +                  EVT_TIMER,
> +                  TPL_CALLBACK,
> +                  NULL,
> +                  NULL,
> +                  &TimeoutEvent
> +                  );
> +
> +  if (EFI_ERROR(Status)) {
> +    goto DONE;
> +  }
> +
> +  Status = gBS->SetTimer (TimeoutEvent,
> +                          TimerRelative,
> +                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
> +
> +  if (EFI_ERROR(Status)) {
> +    goto DONE;
> +  }
> +
> +  do {
>      if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
> -      return EFI_SUCCESS;
> +      Status = EFI_SUCCESS;
> +      goto DONE;
>      }
> 
>      gBS->Stall (XHC_1_MICROSECOND);
> +  } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
> +
> +  Status = EFI_TIMEOUT;
> +
> +DONE:
> +  if (TimeoutEvent != NULL) {
> +    gBS->CloseEvent (TimeoutEvent);
>    }
> 
> -  return EFI_TIMEOUT;
> +  return Status;
>  }
> 
>  /**
> diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> index ab8957c546ee..9cb115363c8b 100644
> --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> @@ -1254,14 +1254,15 @@ XhcCheckUrbResult (
>  /**
>    Execute the transfer by polling the URB. This is a synchronous operation.
> 
> -  @param  Xhc               The XHCI Instance.
> -  @param  CmdTransfer       The executed URB is for cmd transfer or not.
> -  @param  Urb               The URB to execute.
> -  @param  Timeout           The time to wait before abort, in millisecond.
> +  @param  Xhc                    The XHCI Instance.
> +  @param  CmdTransfer            The executed URB is for cmd transfer or not.
> +  @param  Urb                    The URB to execute.
> +  @param  Timeout                The time to wait before abort, in millisecond.
> 
> -  @return EFI_DEVICE_ERROR  The transfer failed due to transfer error.
> -  @return EFI_TIMEOUT       The transfer failed due to time out.
> -  @return EFI_SUCCESS       The transfer finished OK.
> +  @return EFI_DEVICE_ERROR       The transfer failed due to transfer error.
> +  @return EFI_TIMEOUT            The transfer failed due to time out.
> +  @return EFI_SUCCESS            The transfer finished OK.
> +  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could not
> be allocated.
> 
>  **/
>  EFI_STATUS
> @@ -1273,11 +1274,16 @@ XhcExecTransfer (
>    )
>  {
>    EFI_STATUS              Status;
> -  UINTN                   Index;
> -  UINT64                  Loop;
>    UINT8                   SlotId;
>    UINT8                   Dci;
>    BOOLEAN                 Finished;
> +  EFI_EVENT               TimeoutEvent;
> +  BOOLEAN                 IndefiniteTimeout;
> +
> +  Status            = EFI_SUCCESS;
> +  Finished          = FALSE;
> +  TimeoutEvent      = NULL;
> +  IndefiniteTimeout = FALSE;
> 
>    if (CmdTransfer) {
>      SlotId = 0;
> @@ -1291,29 +1297,56 @@ XhcExecTransfer (
>      ASSERT (Dci < 32);
>    }
> 
> -  Status = EFI_SUCCESS;
> -  Loop   = Timeout * XHC_1_MILLISECOND;
>    if (Timeout == 0) {
> -    Loop = 0xFFFFFFFF;
> +    IndefiniteTimeout = TRUE;
> +    goto RINGDOORBELL;
>    }
> 
> +  Status = gBS->CreateEvent (
> +                  EVT_TIMER,
> +                  TPL_CALLBACK,
> +                  NULL,
> +                  NULL,
> +                  &TimeoutEvent
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    goto DONE;
> +  }
> +
> +  Status = gBS->SetTimer (TimeoutEvent,
> +                          TimerRelative,
> +                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
> +
> +  if (EFI_ERROR (Status)) {
> +    goto DONE;
> +  }
> +
> +RINGDOORBELL:
>    XhcRingDoorBell (Xhc, SlotId, Dci);
> 
> -  for (Index = 0; Index < Loop; Index++) {
> +  do {
>      Finished = XhcCheckUrbResult (Xhc, Urb);
>      if (Finished) {
>        break;
>      }
>      gBS->Stall (XHC_1_MICROSECOND);
> -  }
> +  } while (IndefiniteTimeout || EFI_ERROR(gBS->CheckEvent
> + (TimeoutEvent)));
> 
> -  if (Index == Loop) {
> +DONE:
> +  if (EFI_ERROR(Status)) {
> +    Urb->Result = EFI_USB_ERR_NOTEXECUTE;
> +  } else 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.28.0
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2020-09-24  1:22   ` [edk2-devel] " Wu, Hao A
@ 2020-09-29  1:31     ` Wu, Hao A
  0 siblings, 0 replies; 7+ messages in thread
From: Wu, Hao A @ 2020-09-29  1:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wu, Hao A, patrick.henz@hpe.com
  Cc: Wang, Jian J, Ni, Ray

Merged via
Pull request: https://github.com/tianocore/edk2/pull/968
Commit: 71dd80f14f2724ccc99dd7d349b7392adf114019

Best Regards,
Hao Wu

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Wu, Hao
> A
> Sent: Thursday, September 24, 2020 9:22 AM
> To: devel@edk2.groups.io; patrick.henz@hpe.com
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix
> Broken Timeouts
> 
> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
> 
> Best Regards,
> Hao Wu
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Henz,
> > Patrick
> > Sent: Thursday, September 24, 2020 3:36 AM
> > To: devel@edk2.groups.io
> > Cc: Patrick Henz <patrick.henz@hpe.com>; Wang, Jian J
> > <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray
> > <ray.ni@intel.com>
> > Subject: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken
> > Timeouts
> >
> > From: Patrick Henz <patrick.henz@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.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Signed-off-by: Patrick Henz <patrick.henz@hpe.com>
> > ---
> >  MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c   | 59 +++++++++++++++++---
> --
> >  MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 63
> ++++++++++++++++++--
> > ----
> >  2 files changed, 94 insertions(+), 28 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> > b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> > index 42b773ab31be..2bab09415b28 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
> > @@ -423,14 +423,15 @@ XhcClearOpRegBit (
> >    Wait the operation register's bit as specified by Bit
> >    to become set (or clear).
> >
> > -  @param  Xhc          The XHCI Instance.
> > -  @param  Offset       The offset of the operation register.
> > -  @param  Bit          The bit of the register to wait for.
> > -  @param  WaitToSet    Wait the bit to set or clear.
> > -  @param  Timeout      The time to wait before abort (in millisecond, ms).
> > +  @param  Xhc                    The XHCI Instance.
> > +  @param  Offset                 The offset of the operation register.
> > +  @param  Bit                    The bit of the register to wait for.
> > +  @param  WaitToSet              Wait the bit to set or clear.
> > +  @param  Timeout                The time to wait before abort (in millisecond,
> > ms).
> >
> > -  @retval EFI_SUCCESS  The bit successfully changed by host controller.
> > -  @retval EFI_TIMEOUT  The time out occurred.
> > +  @retval EFI_SUCCESS            The bit successfully changed by host
> controller.
> > +  @retval EFI_TIMEOUT            The time out occurred.
> > +  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could
> not
> > be allocated.
> >
> >  **/
> >  EFI_STATUS
> > @@ -442,20 +443,52 @@ XhcWaitOpRegBit (
> >    IN UINT32               Timeout
> >    )
> >  {
> > -  UINT32                  Index;
> > -  UINT64                  Loop;
> > +  EFI_STATUS Status;
> > +  EFI_EVENT  TimeoutEvent;
> >
> > -  Loop   = Timeout * XHC_1_MILLISECOND;
> > +  TimeoutEvent = NULL;
> >
> > -  for (Index = 0; Index < Loop; Index++) {
> > +  if (Timeout == 0) {
> > +    return EFI_TIMEOUT;
> > +  }
> > +
> > +  Status = gBS->CreateEvent (
> > +                  EVT_TIMER,
> > +                  TPL_CALLBACK,
> > +                  NULL,
> > +                  NULL,
> > +                  &TimeoutEvent
> > +                  );
> > +
> > +  if (EFI_ERROR(Status)) {
> > +    goto DONE;
> > +  }
> > +
> > +  Status = gBS->SetTimer (TimeoutEvent,
> > +                          TimerRelative,
> > +                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
> > +
> > +  if (EFI_ERROR(Status)) {
> > +    goto DONE;
> > +  }
> > +
> > +  do {
> >      if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
> > -      return EFI_SUCCESS;
> > +      Status = EFI_SUCCESS;
> > +      goto DONE;
> >      }
> >
> >      gBS->Stall (XHC_1_MICROSECOND);
> > +  } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
> > +
> > +  Status = EFI_TIMEOUT;
> > +
> > +DONE:
> > +  if (TimeoutEvent != NULL) {
> > +    gBS->CloseEvent (TimeoutEvent);
> >    }
> >
> > -  return EFI_TIMEOUT;
> > +  return Status;
> >  }
> >
> >  /**
> > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > index ab8957c546ee..9cb115363c8b 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > @@ -1254,14 +1254,15 @@ XhcCheckUrbResult (
> >  /**
> >    Execute the transfer by polling the URB. This is a synchronous operation.
> >
> > -  @param  Xhc               The XHCI Instance.
> > -  @param  CmdTransfer       The executed URB is for cmd transfer or not.
> > -  @param  Urb               The URB to execute.
> > -  @param  Timeout           The time to wait before abort, in millisecond.
> > +  @param  Xhc                    The XHCI Instance.
> > +  @param  CmdTransfer            The executed URB is for cmd transfer or not.
> > +  @param  Urb                    The URB to execute.
> > +  @param  Timeout                The time to wait before abort, in millisecond.
> >
> > -  @return EFI_DEVICE_ERROR  The transfer failed due to transfer error.
> > -  @return EFI_TIMEOUT       The transfer failed due to time out.
> > -  @return EFI_SUCCESS       The transfer finished OK.
> > +  @return EFI_DEVICE_ERROR       The transfer failed due to transfer error.
> > +  @return EFI_TIMEOUT            The transfer failed due to time out.
> > +  @return EFI_SUCCESS            The transfer finished OK.
> > +  @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could
> not
> > be allocated.
> >
> >  **/
> >  EFI_STATUS
> > @@ -1273,11 +1274,16 @@ XhcExecTransfer (
> >    )
> >  {
> >    EFI_STATUS              Status;
> > -  UINTN                   Index;
> > -  UINT64                  Loop;
> >    UINT8                   SlotId;
> >    UINT8                   Dci;
> >    BOOLEAN                 Finished;
> > +  EFI_EVENT               TimeoutEvent;
> > +  BOOLEAN                 IndefiniteTimeout;
> > +
> > +  Status            = EFI_SUCCESS;
> > +  Finished          = FALSE;
> > +  TimeoutEvent      = NULL;
> > +  IndefiniteTimeout = FALSE;
> >
> >    if (CmdTransfer) {
> >      SlotId = 0;
> > @@ -1291,29 +1297,56 @@ XhcExecTransfer (
> >      ASSERT (Dci < 32);
> >    }
> >
> > -  Status = EFI_SUCCESS;
> > -  Loop   = Timeout * XHC_1_MILLISECOND;
> >    if (Timeout == 0) {
> > -    Loop = 0xFFFFFFFF;
> > +    IndefiniteTimeout = TRUE;
> > +    goto RINGDOORBELL;
> >    }
> >
> > +  Status = gBS->CreateEvent (
> > +                  EVT_TIMER,
> > +                  TPL_CALLBACK,
> > +                  NULL,
> > +                  NULL,
> > +                  &TimeoutEvent
> > +                  );
> > +
> > +  if (EFI_ERROR (Status)) {
> > +    goto DONE;
> > +  }
> > +
> > +  Status = gBS->SetTimer (TimeoutEvent,
> > +                          TimerRelative,
> > +                          EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
> > +
> > +  if (EFI_ERROR (Status)) {
> > +    goto DONE;
> > +  }
> > +
> > +RINGDOORBELL:
> >    XhcRingDoorBell (Xhc, SlotId, Dci);
> >
> > -  for (Index = 0; Index < Loop; Index++) {
> > +  do {
> >      Finished = XhcCheckUrbResult (Xhc, Urb);
> >      if (Finished) {
> >        break;
> >      }
> >      gBS->Stall (XHC_1_MICROSECOND);
> > -  }
> > +  } while (IndefiniteTimeout || EFI_ERROR(gBS->CheckEvent
> > + (TimeoutEvent)));
> >
> > -  if (Index == Loop) {
> > +DONE:
> > +  if (EFI_ERROR(Status)) {
> > +    Urb->Result = EFI_USB_ERR_NOTEXECUTE;
> > +  } else 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.28.0
> >
> >
> >
> >
> >
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2020-09-23 19:36 ` [PATCH v3 1/1] " Henz, Patrick
  2020-09-24  1:22   ` [edk2-devel] " Wu, Hao A
@ 2023-06-07 21:37   ` Jessica Clarke
  2023-06-08 10:32     ` Leif Lindholm
  2023-06-08 16:51     ` Henz, Patrick
  1 sibling, 2 replies; 7+ messages in thread
From: Jessica Clarke @ 2023-06-07 21:37 UTC (permalink / raw)
  To: Henz, Patrick, devel

On Wed, Sep 23, 2020 at 08:36 PM, Henz, Patrick wrote:

>
> From: Patrick Henz <patrick.henz@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.

This strategy doesn't work during ExitBootServices, as called from
XhcExitBootService via XhcHaltHC. The net result is that, if the XHCI
controller fails to halt upon clearing R/S, EDK2 hangs in an infinite
loop (something I just had the joy of debugging).

Jess

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2023-06-07 21:37   ` Jessica Clarke
@ 2023-06-08 10:32     ` Leif Lindholm
  2023-06-08 16:51     ` Henz, Patrick
  1 sibling, 0 replies; 7+ messages in thread
From: Leif Lindholm @ 2023-06-08 10:32 UTC (permalink / raw)
  To: devel, jrtc27, Henz, Patrick
  Cc: Wang, Jian J, Gao, Liming, Wu, Hao A, Ni, Ray

+maintainers

On 2023-06-07 22:37, Jessica Clarke wrote:
> On Wed, Sep 23, 2020 at 08:36 PM, Henz, Patrick wrote:
> 
>>
>> From: Patrick Henz <patrick.henz@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.
> 
> This strategy doesn't work during ExitBootServices, as called from
> XhcExitBootService via XhcHaltHC. The net result is that, if the XHCI
> controller fails to halt upon clearing R/S, EDK2 hangs in an infinite
> loop (something I just had the joy of debugging).
> 
> Jess
> 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts
  2023-06-07 21:37   ` Jessica Clarke
  2023-06-08 10:32     ` Leif Lindholm
@ 2023-06-08 16:51     ` Henz, Patrick
  1 sibling, 0 replies; 7+ messages in thread
From: Henz, Patrick @ 2023-06-08 16:51 UTC (permalink / raw)
  To: Jessica Clarke, Henz@mx0a-002e3701.pphosted.com,
	devel@edk2.groups.io

Hi Jess,

Thank you for reporting this, it's certainly a bug. I'm planning to implement a fix.

Thanks,
Patrick Henz

-----Original Message-----
From: Jessica Clarke <jrtc27@jrtc27.com> 
Sent: Wednesday, June 7, 2023 4:38 PM
To: Henz@mx0a-002e3701.pphosted.com; Henz, Patrick <patrick.henz@hpe.com>; devel@edk2.groups.io
Subject: Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts

On Wed, Sep 23, 2020 at 08:36 PM, Henz, Patrick wrote:

>
> From: Patrick Henz <patrick.henz@hpe.com>
> 
> REF:INVALID URI REMOVED
> g.cgi?id=2948__;!!NpxR!iZG1WFNYYsLpsDRVpII4yD3VcV3qTNWYYBKIkjOpmdsJq4e
> cXWzlnbRiJf9vTEZUUu73BuQmhJJwUHocWQ$
> 
> 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.

This strategy doesn't work during ExitBootServices, as called from XhcExitBootService via XhcHaltHC. The net result is that, if the XHCI controller fails to halt upon clearing R/S, EDK2 hangs in an infinite loop (something I just had the joy of debugging).

Jess

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-06-08 16:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-09-23 19:36 [PATCH v3 0/1] MdeModulePkg/XhciDxe: Fix Broken Timeouts Henz, Patrick
2020-09-23 19:36 ` [PATCH v3 1/1] " Henz, Patrick
2020-09-24  1:22   ` [edk2-devel] " Wu, Hao A
2020-09-29  1:31     ` Wu, Hao A
2023-06-07 21:37   ` Jessica Clarke
2023-06-08 10:32     ` Leif Lindholm
2023-06-08 16:51     ` Henz, Patrick

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox