What about other error return values in *TransferResult?  Both places you check 
for a specific set of errors, but the set is not exhaustive and if a different 
error occurs, will the caller know?

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of
> Tian, Feng
> Sent: Monday, August 24, 2015 8:17 PM
> To: Anbazhagan, Baraneedharan <anbazha...@hp.com>; Zeng, Star
> <star.z...@intel.com>
> Cc: edk2-devel@lists.01.org; Tian, Feng <feng.t...@intel.com>
> Subject: Re: [edk2] [patch] MdeModulePkg/Xhci: Remove TDs from transfer
> ring when timeout happens
> 
> Thanks for your comments, Baranee. I updated the patch as below. Please
> review again.
> 
> ---
>  MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c      |  75 +++++++---
>  MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 193
> +++++++++++++++++++++----
>  MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h |  80 +++++++++++
>  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c   |  51 +++++--
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c | 235
> +++++++++++++++++++++++++++----
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h |  81 ++++++++++-
>  6 files changed, 618 insertions(+), 97 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> index 390ca0a..39c28ab 100644
> --- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> +++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> @@ -905,17 +905,28 @@ XhcControlTransfer (
>    *TransferResult = Urb->Result;
>    *DataLength     = Urb->Completed;
> 
> -  if (*TransferResult == EFI_USB_NOERROR) {
> -    Status = EFI_SUCCESS;
> -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> -    if (EFI_ERROR (RecoveryStatus)) {
> -      DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint
> failed\n"));
> +  if (Status == EFI_TIMEOUT) {
> +    //
> +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> +    //
> +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> +    if (EFI_ERROR(RecoveryStatus)) {
> +      DEBUG((EFI_D_ERROR, "XhcControlTransfer:
> XhcDequeueTrbFromEndpoint failed\n"));
>      }
> -    Status = EFI_DEVICE_ERROR;
>      goto FREE_URB;
>    } else {
> -    goto FREE_URB;
> +    if (*TransferResult == EFI_USB_NOERROR) {
> +      Status = EFI_SUCCESS;
> +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> +      if (EFI_ERROR (RecoveryStatus)) {
> +        DEBUG ((EFI_D_ERROR, "XhcControlTransfer:
> XhcRecoverHaltedEndpoint failed\n"));
> +      }
> +      Status = EFI_DEVICE_ERROR;
> +      goto FREE_URB;
> +    } else {
> +      goto FREE_URB;
> +    }
>    }
> 
>    Xhc->PciIo->Flush (Xhc->PciIo);
> @@ -1241,14 +1252,24 @@ XhcBulkTransfer (
>    *TransferResult = Urb->Result;
>    *DataLength     = Urb->Completed;
> 
> -  if (*TransferResult == EFI_USB_NOERROR) {
> -    Status = EFI_SUCCESS;
> -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> -    if (EFI_ERROR (RecoveryStatus)) {
> -      DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint
> failed\n"));
> +  if (Status == EFI_TIMEOUT) {
> +    //
> +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> +    //
> +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> +    if (EFI_ERROR(RecoveryStatus)) {
> +      DEBUG((EFI_D_ERROR, "XhcBulkTransfer: XhcDequeueTrbFromEndpoint
> failed\n"));
> +    }
> +  } else {
> +    if (*TransferResult == EFI_USB_NOERROR) {
> +      Status = EFI_SUCCESS;
> +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> +      if (EFI_ERROR (RecoveryStatus)) {
> +        DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint
> failed\n"));
> +      }
> +      Status = EFI_DEVICE_ERROR;
>      }
> -    Status = EFI_DEVICE_ERROR;
>    }
> 
>    Xhc->PciIo->Flush (Xhc->PciIo);
> @@ -1538,14 +1559,24 @@ XhcSyncInterruptTransfer (
>    *TransferResult = Urb->Result;
>    *DataLength     = Urb->Completed;
> 
> -  if (*TransferResult == EFI_USB_NOERROR) {
> -    Status = EFI_SUCCESS;
> -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> -    if (EFI_ERROR (RecoveryStatus)) {
> -      DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> XhcRecoverHaltedEndpoint failed\n"));
> +  if (Status == EFI_TIMEOUT) {
> +    //
> +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> +    //
> +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> +    if (EFI_ERROR(RecoveryStatus)) {
> +      DEBUG((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> XhcDequeueTrbFromEndpoint failed\n"));
> +    }
> +  } else {
> +    if (*TransferResult == EFI_USB_NOERROR) {
> +      Status = EFI_SUCCESS;
> +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> +      if (EFI_ERROR (RecoveryStatus)) {
> +        DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> XhcRecoverHaltedEndpoint failed\n"));
> +      }
> +      Status = EFI_DEVICE_ERROR;
>      }
> -    Status = EFI_DEVICE_ERROR;
>    }
> 
>    Xhc->PciIo->Flush (Xhc->PciIo);
> diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> index 05cd616..c25342d 100644
> --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> @@ -645,12 +645,8 @@ XhcRecoverHaltedEndpoint (
>    )
>  {
>    EFI_STATUS                  Status;
> -  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> -  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;
> -  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
>    UINT8                       Dci;
>    UINT8                       SlotId;
> -  EFI_PHYSICAL_ADDRESS        PhyAddr;
> 
>    Status = EFI_SUCCESS;
>    SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
> @@ -665,17 +661,7 @@ XhcRecoverHaltedEndpoint (
>    //
>    // 1) Send Reset endpoint command to transit from halt to stop state
>    //
> -  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));
> -  CmdTrbResetED.CycleBit = 1;
> -  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;
> -  CmdTrbResetED.EDID     = Dci;
> -  CmdTrbResetED.SlotId   = SlotId;
> -  Status = XhcCmdTransfer (
> -             Xhc,
> -             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,
> -             XHC_GENERIC_TIMEOUT,
> -             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> -             );
> +  Status = XhcResetEndpoint(Xhc, SlotId, Dci);
>    if (EFI_ERROR(Status)) {
>      DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint
> Failed, Status = %r\n", Status));
>      goto Done;
> @@ -684,22 +670,70 @@ XhcRecoverHaltedEndpoint (
>    //
>    // 2)Set dequeue pointer
>    //
> -  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
> -  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
> -  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;
> -  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> -  CmdSetTRDeq.CycleBit = 1;
> -  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> -  CmdSetTRDeq.Endpoint = Dci;
> -  CmdSetTRDeq.SlotId   = SlotId;
> -  Status = XhcCmdTransfer (
> -             Xhc,
> -             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> -             XHC_GENERIC_TIMEOUT,
> -             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> -             );
> +  Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Transfer Ring
> Dequeue Pointer Failed, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // 3)Ring the doorbell to transit from stop to active
> +  //
> +  XhcRingDoorBell (Xhc, SlotId, Dci);
> +
> +Done:
> +  return Status;
> +}
> +
> +/**
> +  System software shall use a Stop Endpoint Command (section 4.6.9) and
> the Set TR Dequeue Pointer
> +  Command (section 4.6.10) to remove the timed-out TDs from the xHC
> transfer ring. The next write to
> +  the Doorbell of the Endpoint will transition the Endpoint Context from the
> Stopped to the Running
> +  state.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  Urb                   The urb which doesn't get completed in a 
> specified
> timeout range.
> +
> +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> +  @retval Others                Failed to stop the endpoint and dequeue the 
> TDs.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcDequeueTrbFromEndpoint (
> +  IN  USB_XHCI_INSTANCE   *Xhc,
> +  IN  URB                 *Urb
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  UINT8                       Dci;
> +  UINT8                       SlotId;
> +
> +  Status = EFI_SUCCESS;
> +  SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
> +  if (SlotId == 0) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
> +  ASSERT (Dci < 32);
> +
> +  DEBUG ((EFI_D_INFO, "Stop Slot = %x,Dci = %x\n", SlotId, Dci));
> +
> +  //
> +  // 1) Send Stop endpoint command to stop xHC from executing of the TDs
> on the endpoint
> +  //
> +  Status = XhcStopEndpoint(Xhc, SlotId, Dci);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint
> Failed, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // 2)Set dequeue pointer
> +  //
> +  Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);
>    if (EFI_ERROR(Status)) {
> -    DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Dequeue
> Pointer Failed, Status = %r\n", Status));
> +    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Set Transfer Ring
> Dequeue Pointer Failed, Status = %r\n", Status));
>      goto Done;
>    }
> 
> @@ -3062,6 +3096,105 @@ XhcStopEndpoint (
>  }
> 
>  /**
> +  Reset endpoint through XHCI's Reset_Endpoint cmd.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  SlotId                The slot id to be configured.
> +  @param  Dci                   The device context index of endpoint.
> +
> +  @retval EFI_SUCCESS           Reset endpoint successfully.
> +  @retval Others                Failed to reset endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcResetEndpoint (
> +  IN USB_XHCI_INSTANCE      *Xhc,
> +  IN UINT8                  SlotId,
> +  IN UINT8                  Dci
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> +  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;
> +
> +  DEBUG ((EFI_D_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n",
> SlotId, Dci));
> +
> +  //
> +  // Send stop endpoint command to transit Endpoint from running to stop
> state
> +  //
> +  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));
> +  CmdTrbResetED.CycleBit = 1;
> +  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;
> +  CmdTrbResetED.EDID     = Dci;
> +  CmdTrbResetED.SlotId   = SlotId;
> +  Status = XhcCmdTransfer (
> +             Xhc,
> +             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,
> +             XHC_GENERIC_TIMEOUT,
> +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status
> = %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Set transfer ring dequeue pointer through XHCI's
> Set_Tr_Dequeue_Pointer cmd.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  SlotId                The slot id to be configured.
> +  @param  Dci                   The device context index of endpoint.
> +  @param  Urb                   The dequeue pointer of the transfer ring 
> specified
> +                                by the urb to be updated.
> +
> +  @retval EFI_SUCCESS           Set transfer ring dequeue pointer succeeds.
> +  @retval Others                Failed to set transfer ring dequeue pointer.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcSetTrDequeuePointer (
> +  IN USB_XHCI_INSTANCE      *Xhc,
> +  IN UINT8                  SlotId,
> +  IN UINT8                  Dci,
> +  IN URB                    *Urb
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> +  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
> +  EFI_PHYSICAL_ADDRESS        PhyAddr;
> +
> +  DEBUG ((EFI_D_INFO, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x,
> Urb = 0x%x\n", SlotId, Dci, Urb));
> +
> +  //
> +  // Send stop endpoint command to transit Endpoint from running to stop
> state
> +  //
> +  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
> +  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
> +  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring-
> >RingPCS;
> +  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> +  CmdSetTRDeq.CycleBit = 1;
> +  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> +  CmdSetTRDeq.Endpoint = Dci;
> +  CmdSetTRDeq.SlotId   = SlotId;
> +  Status = XhcCmdTransfer (
> +             Xhc,
> +             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> +             XHC_GENERIC_TIMEOUT,
> +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue
> Pointer Failed, Status = %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
>    Set interface through XHCI's Configure_Endpoint cmd.
> 
>    @param  Xhc           The XHCI Instance.
> diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> index 1b6e345..931c7ef 100644
> --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> @@ -1318,6 +1318,86 @@ XhcRecoverHaltedEndpoint (
>    );
> 
>  /**
> +  System software shall use a Stop Endpoint Command (section 4.6.9) and
> the Set TR Dequeue Pointer
> +  Command (section 4.6.10) to remove the timed-out TDs from the xHC
> transfer ring. The next write to
> +  the Doorbell of the Endpoint will transition the Endpoint Context from the
> Stopped to the Running
> +  state.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  Urb                   The urb which doesn't get completed in a 
> specified
> timeout range.
> +
> +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> +  @retval Others                Failed to stop the endpoint and dequeue the 
> TDs.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcDequeueTrbFromEndpoint (
> +  IN  USB_XHCI_INSTANCE   *Xhc,
> +  IN  URB                 *Urb
> +  );
> +
> +/**
> +  Stop endpoint through XHCI's Stop_Endpoint cmd.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  SlotId                The slot id to be configured.
> +  @param  Dci                   The device context index of endpoint.
> +
> +  @retval EFI_SUCCESS           Stop endpoint successfully.
> +  @retval Others                Failed to stop endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcStopEndpoint (
> +  IN USB_XHCI_INSTANCE      *Xhc,
> +  IN UINT8                  SlotId,
> +  IN UINT8                  Dci
> +  );
> +
> +/**
> +  Reset endpoint through XHCI's Reset_Endpoint cmd.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  SlotId                The slot id to be configured.
> +  @param  Dci                   The device context index of endpoint.
> +
> +  @retval EFI_SUCCESS           Reset endpoint successfully.
> +  @retval Others                Failed to reset endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcResetEndpoint (
> +  IN USB_XHCI_INSTANCE      *Xhc,
> +  IN UINT8                  SlotId,
> +  IN UINT8                  Dci
> +  );
> +
> +/**
> +  Set transfer ring dequeue pointer through XHCI's
> Set_Tr_Dequeue_Pointer cmd.
> +
> +  @param  Xhc                   The XHCI Instance.
> +  @param  SlotId                The slot id to be configured.
> +  @param  Dci                   The device context index of endpoint.
> +  @param  Urb                   The dequeue pointer of the transfer ring 
> specified
> +                                by the urb to be updated.
> +
> +  @retval EFI_SUCCESS           Set transfer ring dequeue pointer succeeds.
> +  @retval Others                Failed to set transfer ring dequeue pointer.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcSetTrDequeuePointer (
> +  IN USB_XHCI_INSTANCE      *Xhc,
> +  IN UINT8                  SlotId,
> +  IN UINT8                  Dci,
> +  IN URB                    *Urb
> +  );
> +
> +/**
>    Create a new URB for a new transaction.
> 
>    @param  Xhc       The XHCI Instance
> diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> index 2f16b82..eaea38d 100644
> --- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> @@ -648,17 +648,28 @@ XhcPeiControlTransfer (
>    *TransferResult = Urb->Result;
>    *DataLength     = Urb->Completed;
> 
> -  if (*TransferResult == EFI_USB_NOERROR) {
> -    Status = EFI_SUCCESS;
> -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> -    RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> -    if (EFI_ERROR (RecoveryStatus)) {
> -      DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer:
> XhcPeiRecoverHaltedEndpoint failed\n"));
> +  if (Status == EFI_TIMEOUT) {
> +    //
> +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> +    //
> +    RecoveryStatus = XhcPeiDequeueTrbFromEndpoint(Xhc, Urb);
> +    if (EFI_ERROR(RecoveryStatus)) {
> +      DEBUG((EFI_D_ERROR, "XhcPeiControlTransfer:
> XhcPeiDequeueTrbFromEndpoint failed\n"));
>      }
> -    Status = EFI_DEVICE_ERROR;
>      goto FREE_URB;
>    } else {
> -    goto FREE_URB;
> +    if (*TransferResult == EFI_USB_NOERROR) {
> +      Status = EFI_SUCCESS;
> +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> +      RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> +      if (EFI_ERROR (RecoveryStatus)) {
> +        DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer:
> XhcPeiRecoverHaltedEndpoint failed\n"));
> +      }
> +      Status = EFI_DEVICE_ERROR;
> +      goto FREE_URB;
> +    } else {
> +      goto FREE_URB;
> +    }
>    }
> 
>    //
> @@ -960,14 +971,24 @@ XhcPeiBulkTransfer (
>    *TransferResult = Urb->Result;
>    *DataLength     = Urb->Completed;
> 
> -  if (*TransferResult == EFI_USB_NOERROR) {
> -    Status = EFI_SUCCESS;
> -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> -    RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> -    if (EFI_ERROR (RecoveryStatus)) {
> -      DEBUG ((EFI_D_ERROR, "XhcPeiBulkTransfer:
> XhcPeiRecoverHaltedEndpoint failed\n"));
> +  if (Status == EFI_TIMEOUT) {
> +    //
> +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> +    //
> +    RecoveryStatus = XhcPeiDequeueTrbFromEndpoint(Xhc, Urb);
> +    if (EFI_ERROR(RecoveryStatus)) {
> +      DEBUG((EFI_D_ERROR, "XhcPeiBulkTransfer:
> XhcPeiDequeueTrbFromEndpoint failed\n"));
> +    }
> +  } else {
> +    if (*TransferResult == EFI_USB_NOERROR) {
> +      Status = EFI_SUCCESS;
> +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> +      RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> +      if (EFI_ERROR (RecoveryStatus)) {
> +        DEBUG ((EFI_D_ERROR, "XhcPeiBulkTransfer:
> XhcPeiRecoverHaltedEndpoint failed\n"));
> +      }
> +      Status = EFI_DEVICE_ERROR;
>      }
> -    Status = EFI_DEVICE_ERROR;
>    }
> 
>    XhcPeiFreeUrb (Xhc, Urb);
> diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> index eedf377..3632e8a 100644
> --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> @@ -444,12 +444,8 @@ XhcPeiRecoverHaltedEndpoint (
>    )
>  {
>    EFI_STATUS                  Status;
> -  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> -  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;
> -  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
>    UINT8                       Dci;
>    UINT8                       SlotId;
> -  EFI_PHYSICAL_ADDRESS        PhyAddr;
> 
>    Status = EFI_SUCCESS;
>    SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
> @@ -463,17 +459,7 @@ XhcPeiRecoverHaltedEndpoint (
>    //
>    // 1) Send Reset endpoint command to transit from halt to stop state
>    //
> -  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));
> -  CmdTrbResetED.CycleBit = 1;
> -  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;
> -  CmdTrbResetED.EDID     = Dci;
> -  CmdTrbResetED.SlotId   = SlotId;
> -  Status = XhcPeiCmdTransfer (
> -             Xhc,
> -             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,
> -             XHC_GENERIC_TIMEOUT,
> -             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> -             );
> +  Status = XhcPeiResetEndpoint (Xhc, SlotId, Dci);
>    if (EFI_ERROR(Status)) {
>      DEBUG ((EFI_D_ERROR, "XhcPeiRecoverHaltedEndpoint: Reset Endpoint
> Failed, Status = %r\n", Status));
>      goto Done;
> @@ -482,20 +468,7 @@ XhcPeiRecoverHaltedEndpoint (
>    //
>    // 2) Set dequeue pointer
>    //
> -  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
> -  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
> -  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;
> -  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> -  CmdSetTRDeq.CycleBit = 1;
> -  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> -  CmdSetTRDeq.Endpoint = Dci;
> -  CmdSetTRDeq.SlotId   = SlotId;
> -  Status = XhcPeiCmdTransfer (
> -             Xhc,
> -             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> -             XHC_GENERIC_TIMEOUT,
> -             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> -             );
> +  Status = XhcPeiSetTrDequeuePointer (Xhc, SlotId, Dci, Urb);
>    if (EFI_ERROR(Status)) {
>      DEBUG ((EFI_D_ERROR, "XhcPeiRecoverHaltedEndpoint: Set Dequeue
> Pointer Failed, Status = %r\n", Status));
>      goto Done;
> @@ -511,6 +484,65 @@ Done:
>  }
> 
>  /**
> +  System software shall use a Stop Endpoint Command (section 4.6.9) and
> the Set TR Dequeue Pointer
> +  Command (section 4.6.10) to remove the timed-out TDs from the xHC
> transfer ring. The next write to
> +  the Doorbell of the Endpoint will transition the Endpoint Context from the
> Stopped to the Running
> +  state.
> +
> +  @param  Xhc                   The XHCI device.
> +  @param  Urb                   The urb which doesn't get completed in a 
> specified
> timeout range.
> +
> +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> +  @retval Others                Failed to stop the endpoint and dequeue the 
> TDs.
> +
> +**/
> +EFI_STATUS
> +XhcPeiDequeueTrbFromEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN URB                *Urb
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  UINT8                       Dci;
> +  UINT8                       SlotId;
> +
> +  Status = EFI_SUCCESS;
> +  SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
> +  if (SlotId == 0) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  Dci = XhcPeiEndpointToDci (Urb->Ep.EpAddr, (UINT8) (Urb->Ep.Direction));
> +
> +  DEBUG ((EFI_D_INFO, "XhcPeiDequeueTrbFromEndpoint: Stop Slot = %x,
> Dci = %x\n", SlotId, Dci));
> +
> +  //
> +  // 1) Send Stop endpoint command to stop endpoint.
> +  //
> +  Status = XhcPeiStopEndpoint (Xhc, SlotId, Dci);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcPeiDequeueTrbFromEndpoint: Stop
> Endpoint Failed, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // 2) Set dequeue pointer
> +  //
> +  Status = XhcPeiSetTrDequeuePointer (Xhc, SlotId, Dci, Urb);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcPeiDequeueTrbFromEndpoint: Set Dequeue
> Pointer Failed, Status = %r\n", Status));
> +    goto Done;
> +  }
> +
> +  //
> +  // 3) Ring the doorbell to transit from stop to active
> +  //
> +  XhcPeiRingDoorBell (Xhc, SlotId, Dci);
> +
> +Done:
> +  return Status;
> +}
> +
> +/**
>    Check if the Trb is a transaction of the URB.
> 
>    @param Trb        The TRB to be checked
> @@ -2254,6 +2286,151 @@ XhcPeiConfigHubContext64 (
>  }
> 
>  /**
> +  Stop endpoint through XHCI's Stop_Endpoint cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +
> +  @retval EFI_SUCCESS   Stop endpoint successfully.
> +  @retval Others        Failed to stop endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiStopEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EVT_TRB_COMMAND_COMPLETION    *EvtTrb;
> +  CMD_TRB_STOP_ENDPOINT         CmdTrbStopED;
> +
> +  DEBUG ((EFI_D_INFO, "XhcPeiStopEndpoint: Slot = 0x%x, Dci = 0x%x\n",
> SlotId, Dci));
> +
> +  //
> +  // Send stop endpoint command to transit Endpoint from running to stop
> state
> +  //
> +  ZeroMem (&CmdTrbStopED, sizeof (CmdTrbStopED));
> +  CmdTrbStopED.CycleBit = 1;
> +  CmdTrbStopED.Type     = TRB_TYPE_STOP_ENDPOINT;
> +  CmdTrbStopED.EDID     = Dci;
> +  CmdTrbStopED.SlotId   = SlotId;
> +  Status = XhcPeiCmdTransfer (
> +             Xhc,
> +             (TRB_TEMPLATE *) (UINTN) &CmdTrbStopED,
> +             XHC_GENERIC_TIMEOUT,
> +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcPeiStopEndpoint: Stop Endpoint Failed,
> Status = %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Reset endpoint through XHCI's Reset_Endpoint cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +
> +  @retval EFI_SUCCESS   Reset endpoint successfully.
> +  @retval Others        Failed to reset endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiResetEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> +  CMD_TRB_RESET_ENDPOINT      CmdTrbResetED;
> +
> +  DEBUG ((EFI_D_INFO, "XhcPeiResetEndpoint: Slot = 0x%x, Dci = 0x%x\n",
> SlotId, Dci));
> +
> +  //
> +  // Send stop endpoint command to transit Endpoint from running to stop
> state
> +  //
> +  ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));
> +  CmdTrbResetED.CycleBit = 1;
> +  CmdTrbResetED.Type     = TRB_TYPE_RESET_ENDPOINT;
> +  CmdTrbResetED.EDID     = Dci;
> +  CmdTrbResetED.SlotId   = SlotId;
> +  Status = XhcPeiCmdTransfer (
> +             Xhc,
> +             (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,
> +             XHC_GENERIC_TIMEOUT,
> +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcPeiResetEndpoint: Reset Endpoint Failed,
> Status = %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Set transfer ring dequeue pointer through XHCI's
> Set_Tr_Dequeue_Pointer cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +  @param  Urb           The dequeue pointer of the transfer ring specified
> +                        by the urb to be updated.
> +
> +  @retval EFI_SUCCESS   Set transfer ring dequeue pointer succeeds.
> +  @retval Others        Failed to set transfer ring dequeue pointer.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiSetTrDequeuePointer (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci,
> +  IN URB                *Urb
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> +  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
> +  EFI_PHYSICAL_ADDRESS        PhyAddr;
> +
> +  DEBUG ((EFI_D_INFO, "XhcPeiSetTrDequeuePointer: Slot = 0x%x, Dci =
> 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb));
> +
> +  //
> +  // Send stop endpoint command to transit Endpoint from running to stop
> state
> +  //
> +  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
> +  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
> +  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring-
> >RingPCS;
> +  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> +  CmdSetTRDeq.CycleBit = 1;
> +  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> +  CmdSetTRDeq.Endpoint = Dci;
> +  CmdSetTRDeq.SlotId   = SlotId;
> +  Status = XhcPeiCmdTransfer (
> +             Xhc,
> +             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> +             XHC_GENERIC_TIMEOUT,
> +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((EFI_D_ERROR, "XhcPeiSetTrDequeuePointer: Set TR Dequeue
> Pointer Failed, Status = %r\n", Status));
> +  }
> +
> +  return Status;
> +}
> +
> +/**
>    Check if there is a new generated event.
> 
>    @param  Xhc           The XHCI device.
> diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> index 19672d0..b3d4c45 100644
> --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> @@ -1,7 +1,7 @@
>  /** @file
>  Private Header file for Usb Host Controller PEIM
> 
> -Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
> 
>  This program and the accompanying materials
>  are licensed and made available under the terms and conditions
> @@ -939,6 +939,66 @@ XhcPeiSetConfigCmd64 (
>    );
> 
>  /**
> +  Stop endpoint through XHCI's Stop_Endpoint cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +
> +  @retval EFI_SUCCESS   Stop endpoint successfully.
> +  @retval Others        Failed to stop endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiStopEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci
> +  );
> +
> +/**
> +  Reset endpoint through XHCI's Reset_Endpoint cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +
> +  @retval EFI_SUCCESS   Reset endpoint successfully.
> +  @retval Others        Failed to reset endpoint.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiResetEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci
> +  );
> +
> +/**
> +  Set transfer ring dequeue pointer through XHCI's
> Set_Tr_Dequeue_Pointer cmd.
> +
> +  @param  Xhc           The XHCI device.
> +  @param  SlotId        The slot id of the target device.
> +  @param  Dci           The device context index of the target slot or 
> endpoint.
> +  @param  Urb           The dequeue pointer of the transfer ring specified
> +                        by the urb to be updated.
> +
> +  @retval EFI_SUCCESS   Set transfer ring dequeue pointer succeeds.
> +  @retval Others        Failed to set transfer ring dequeue pointer.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +XhcPeiSetTrDequeuePointer (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN UINT8              SlotId,
> +  IN UINT8              Dci,
> +  IN URB                *Urb
> +  );
> +
> +/**
>    Assign and initialize the device slot for a new device.
> 
>    @param  Xhc                   The XHCI device.
> @@ -1067,6 +1127,25 @@ XhcPeiRecoverHaltedEndpoint (
>    );
> 
>  /**
> +  System software shall use a Stop Endpoint Command (section 4.6.9) and
> the Set TR Dequeue Pointer
> +  Command (section 4.6.10) to remove the timed-out TDs from the xHC
> transfer ring. The next write to
> +  the Doorbell of the Endpoint will transition the Endpoint Context from the
> Stopped to the Running
> +  state.
> +
> +  @param  Xhc                   The XHCI device.
> +  @param  Urb                   The urb which doesn't get completed in a 
> specified
> timeout range.
> +
> +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> +  @retval Others                Failed to stop the endpoint and dequeue the 
> TDs.
> +
> +**/
> +EFI_STATUS
> +XhcPeiDequeueTrbFromEndpoint (
> +  IN PEI_XHC_DEV        *Xhc,
> +  IN URB                *Urb
> +  );
> +
> +/**
>    Create a new URB for a new transaction.
> 
>    @param  Xhc       The XHCI device
> --
> 1.9.5.msysgit.0
> 
> 
> -----Original Message-----
> From: Anbazhagan, Baraneedharan [mailto:anbazha...@hp.com]
> Sent: Tuesday, August 25, 2015 02:57
> To: Tian, Feng; Zeng, Star
> Cc: edk2-devel@lists.01.org
> Subject: RE: [edk2] [patch] MdeModulePkg/Xhci: Remove TDs from transfer
> ring when timeout happens
> 
> Could you please create a separate function for 'Set dequeue pointer' since
> it's already in XhcRecoverHaltedEndpoint as well?
> 
> -Baranee
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of
> > Tian Feng
> > Sent: Monday, August 24, 2015 12:53 AM
> > To: star.z...@intel.com
> > Cc: edk2-devel@lists.01.org; Feng Tian
> > Subject: [edk2] [patch] MdeModulePkg/Xhci: Remove TDs from transfer
> > ring when timeout happens
> >
> > The error handling for timeout case is enhanced to remove TDs from
> transfer ring.
> > The original code only removed s/w URB, but the h/w transfer
> > descriptor TDs didn't get removed. It would cause data lost for data
> > stream peripheral, such as usb-to- serial device, from the s/w perspective.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Feng Tian <feng.t...@intel.com>
> > Cc: Star Zeng <star.z...@intel.com>
> > ---
> >  MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c      | 75 ++++++++++++++++++++-
> -------
> >  MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 77
> > ++++++++++++++++++++++++++++
> MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h | 39 +++++++++++++++
> >  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c   | 51 +++++++++++++------
> >  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c | 86
> > ++++++++++++++++++++++++++++++++
> > ++++++++++++++++++++++++++++++++
> MdeModulePkg/Bus/Pci/XhciPei/XhciSche
> > ++++++++++++++++++++++++++++++++ d.h
> > | 21 +++++++-
> >  6 files changed, 311 insertions(+), 38 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> > b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> > index 390ca0a..39c28ab 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
> > @@ -905,17 +905,28 @@ XhcControlTransfer (
> >    *TransferResult = Urb->Result;
> >    *DataLength     = Urb->Completed;
> >
> > -  if (*TransferResult == EFI_USB_NOERROR) {
> > -    Status = EFI_SUCCESS;
> > -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > -    if (EFI_ERROR (RecoveryStatus)) {
> > -      DEBUG ((EFI_D_ERROR, "XhcControlTransfer:
> XhcRecoverHaltedEndpoint
> > failed\n"));
> > +  if (Status == EFI_TIMEOUT) {
> > +    //
> > +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> > +    //
> > +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> > +    if (EFI_ERROR(RecoveryStatus)) {
> > +      DEBUG((EFI_D_ERROR, "XhcControlTransfer:
> > + XhcDequeueTrbFromEndpoint failed\n"));
> >      }
> > -    Status = EFI_DEVICE_ERROR;
> >      goto FREE_URB;
> >    } else {
> > -    goto FREE_URB;
> > +    if (*TransferResult == EFI_USB_NOERROR) {
> > +      Status = EFI_SUCCESS;
> > +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > +      if (EFI_ERROR (RecoveryStatus)) {
> > +        DEBUG ((EFI_D_ERROR, "XhcControlTransfer:
> > + XhcRecoverHaltedEndpoint
> > failed\n"));
> > +      }
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto FREE_URB;
> > +    } else {
> > +      goto FREE_URB;
> > +    }
> >    }
> >
> >    Xhc->PciIo->Flush (Xhc->PciIo);
> > @@ -1241,14 +1252,24 @@ XhcBulkTransfer (
> >    *TransferResult = Urb->Result;
> >    *DataLength     = Urb->Completed;
> >
> > -  if (*TransferResult == EFI_USB_NOERROR) {
> > -    Status = EFI_SUCCESS;
> > -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > -    if (EFI_ERROR (RecoveryStatus)) {
> > -      DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint
> failed\n"));
> > +  if (Status == EFI_TIMEOUT) {
> > +    //
> > +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> > +    //
> > +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> > +    if (EFI_ERROR(RecoveryStatus)) {
> > +      DEBUG((EFI_D_ERROR, "XhcBulkTransfer:
> XhcDequeueTrbFromEndpoint
> > failed\n"));
> > +    }
> > +  } else {
> > +    if (*TransferResult == EFI_USB_NOERROR) {
> > +      Status = EFI_SUCCESS;
> > +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > +      if (EFI_ERROR (RecoveryStatus)) {
> > +        DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint
> failed\n"));
> > +      }
> > +      Status = EFI_DEVICE_ERROR;
> >      }
> > -    Status = EFI_DEVICE_ERROR;
> >    }
> >
> >    Xhc->PciIo->Flush (Xhc->PciIo);
> > @@ -1538,14 +1559,24 @@ XhcSyncInterruptTransfer (
> >    *TransferResult = Urb->Result;
> >    *DataLength     = Urb->Completed;
> >
> > -  if (*TransferResult == EFI_USB_NOERROR) {
> > -    Status = EFI_SUCCESS;
> > -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > -    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > -    if (EFI_ERROR (RecoveryStatus)) {
> > -      DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> XhcRecoverHaltedEndpoint
> > failed\n"));
> > +  if (Status == EFI_TIMEOUT) {
> > +    //
> > +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> > +    //
> > +    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
> > +    if (EFI_ERROR(RecoveryStatus)) {
> > +      DEBUG((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> > + XhcDequeueTrbFromEndpoint
> > failed\n"));
> > +    }
> > +  } else {
> > +    if (*TransferResult == EFI_USB_NOERROR) {
> > +      Status = EFI_SUCCESS;
> > +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > +      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
> > +      if (EFI_ERROR (RecoveryStatus)) {
> > +        DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer:
> > + XhcRecoverHaltedEndpoint
> > failed\n"));
> > +      }
> > +      Status = EFI_DEVICE_ERROR;
> >      }
> > -    Status = EFI_DEVICE_ERROR;
> >    }
> >
> >    Xhc->PciIo->Flush (Xhc->PciIo);
> > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > index 05cd616..bbaa81f 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
> > @@ -713,6 +713,83 @@ Done:
> >  }
> >
> >  /**
> > +  System software shall use a Stop Endpoint Command (section 4.6.9)
> > + and the Set TR Dequeue Pointer  Command (section 4.6.10) to remove
> > + the timed-out TDs from the xHC transfer ring. The next write to  the
> > + Doorbell of the Endpoint will transition the Endpoint Context from
> > + the Stopped to
> > the Running  state.
> > +
> > +  @param  Xhc                   The XHCI Instance.
> > +  @param  Urb                   The urb which doesn't get completed in a
> specified timeout
> > range.
> > +
> > +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> > +  @retval Others                Failed to stop the endpoint and dequeue 
> > the TDs.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XhcDequeueTrbFromEndpoint (
> > +  IN  USB_XHCI_INSTANCE   *Xhc,
> > +  IN  URB                 *Urb
> > +  )
> > +{
> > +  EFI_STATUS                  Status;
> > +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> > +  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
> > +  UINT8                       Dci;
> > +  UINT8                       SlotId;
> > +  EFI_PHYSICAL_ADDRESS        PhyAddr;
> > +
> > +  Status = EFI_SUCCESS;
> > +  SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);  if (SlotId
> > + ==
> > + 0) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +  Dci = XhcEndpointToDci (Urb->Ep.EpAddr,
> > + (UINT8)(Urb->Ep.Direction)); ASSERT (Dci < 32);
> > +
> > +  DEBUG ((EFI_D_INFO, "Stop Slot = %x,Dci = %x\n", SlotId, Dci));
> > +
> > +  //
> > +  // 1) Send Stop endpoint command to stop xHC from executing of the
> > + TDs on the endpoint  //  Status = XhcStopEndpoint(Xhc, SlotId, Dci);
> > + if (EFI_ERROR(Status)) {
> > +    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint
> > + Failed,
> > Status = %r\n", Status));
> > +    goto Done;
> > +  }
> > +
> > +  //
> > +  // 2)Set dequeue pointer
> > +  //
> > +  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));  PhyAddr =
> > + UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue,
> > + sizeof
> > (CMD_SET_TR_DEQ_POINTER));
> > +  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring-
> >RingPCS;
> > +  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> > +  CmdSetTRDeq.CycleBit = 1;
> > +  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> > +  CmdSetTRDeq.Endpoint = Dci;
> > +  CmdSetTRDeq.SlotId   = SlotId;
> > +  Status = XhcCmdTransfer (
> > +             Xhc,
> > +             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> > +             XHC_GENERIC_TIMEOUT,
> > +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> > +             );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Set Dequeue
> > + Pointer Failed,
> > Status = %r\n", Status));
> > +    goto Done;
> > +  }
> > +
> > +  //
> > +  // 3)Ring the doorbell to transit from stop to active  //
> > + XhcRingDoorBell (Xhc, SlotId, Dci);
> > +
> > +Done:
> > +  return Status;
> > +}
> > +
> > +/**
> >    Create XHCI event ring.
> >
> >    @param  Xhc                 The XHCI Instance.
> > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> > b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> > index 1b6e345..68b2977 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
> > @@ -1318,6 +1318,45 @@ XhcRecoverHaltedEndpoint (
> >    );
> >
> >  /**
> > +  System software shall use a Stop Endpoint Command (section 4.6.9)
> > + and the Set TR Dequeue Pointer  Command (section 4.6.10) to remove
> > + the timed-out TDs from the xHC transfer ring. The next write to  the
> > + Doorbell of the Endpoint will transition the Endpoint Context from
> > + the Stopped to
> > the Running  state.
> > +
> > +  @param  Xhc                   The XHCI Instance.
> > +  @param  Urb                   The urb which doesn't get completed in a
> specified timeout
> > range.
> > +
> > +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> > +  @retval Others                Failed to stop the endpoint and dequeue 
> > the TDs.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XhcDequeueTrbFromEndpoint (
> > +  IN  USB_XHCI_INSTANCE   *Xhc,
> > +  IN  URB                 *Urb
> > +  );
> > +
> > +/**
> > +  Stop endpoint through XHCI's Stop_Endpoint cmd.
> > +
> > +  @param  Xhc                   The XHCI Instance.
> > +  @param  SlotId                The slot id to be configured.
> > +  @param  Dci                   The device context index of endpoint.
> > +
> > +  @retval EFI_SUCCESS           Stop endpoint successfully.
> > +  @retval Others                Failed to stop endpoint.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XhcStopEndpoint (
> > +  IN USB_XHCI_INSTANCE      *Xhc,
> > +  IN UINT8                  SlotId,
> > +  IN UINT8                  Dci
> > +  );
> > +
> > +/**
> >    Create a new URB for a new transaction.
> >
> >    @param  Xhc       The XHCI Instance
> > diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> > b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> > index 2f16b82..eaea38d 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> > @@ -648,17 +648,28 @@ XhcPeiControlTransfer (
> >    *TransferResult = Urb->Result;
> >    *DataLength     = Urb->Completed;
> >
> > -  if (*TransferResult == EFI_USB_NOERROR) {
> > -    Status = EFI_SUCCESS;
> > -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > -    RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> > -    if (EFI_ERROR (RecoveryStatus)) {
> > -      DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer:
> XhcPeiRecoverHaltedEndpoint
> > failed\n"));
> > +  if (Status == EFI_TIMEOUT) {
> > +    //
> > +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> > +    //
> > +    RecoveryStatus = XhcPeiDequeueTrbFromEndpoint(Xhc, Urb);
> > +    if (EFI_ERROR(RecoveryStatus)) {
> > +      DEBUG((EFI_D_ERROR, "XhcPeiControlTransfer:
> > + XhcPeiDequeueTrbFromEndpoint failed\n"));
> >      }
> > -    Status = EFI_DEVICE_ERROR;
> >      goto FREE_URB;
> >    } else {
> > -    goto FREE_URB;
> > +    if (*TransferResult == EFI_USB_NOERROR) {
> > +      Status = EFI_SUCCESS;
> > +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > +      RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> > +      if (EFI_ERROR (RecoveryStatus)) {
> > +        DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer:
> > + XhcPeiRecoverHaltedEndpoint
> > failed\n"));
> > +      }
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto FREE_URB;
> > +    } else {
> > +      goto FREE_URB;
> > +    }
> >    }
> >
> >    //
> > @@ -960,14 +971,24 @@ XhcPeiBulkTransfer (
> >    *TransferResult = Urb->Result;
> >    *DataLength     = Urb->Completed;
> >
> > -  if (*TransferResult == EFI_USB_NOERROR) {
> > -    Status = EFI_SUCCESS;
> > -  } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > -    RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> > -    if (EFI_ERROR (RecoveryStatus)) {
> > -      DEBUG ((EFI_D_ERROR, "XhcPeiBulkTransfer:
> XhcPeiRecoverHaltedEndpoint
> > failed\n"));
> > +  if (Status == EFI_TIMEOUT) {
> > +    //
> > +    // The transfer timed out. Abort the transfer by dequeueing of the TD.
> > +    //
> > +    RecoveryStatus = XhcPeiDequeueTrbFromEndpoint(Xhc, Urb);
> > +    if (EFI_ERROR(RecoveryStatus)) {
> > +      DEBUG((EFI_D_ERROR, "XhcPeiBulkTransfer:
> > + XhcPeiDequeueTrbFromEndpoint
> > failed\n"));
> > +    }
> > +  } else {
> > +    if (*TransferResult == EFI_USB_NOERROR) {
> > +      Status = EFI_SUCCESS;
> > +    } else if (*TransferResult == EFI_USB_ERR_STALL) {
> > +      RecoveryStatus = XhcPeiRecoverHaltedEndpoint(Xhc, Urb);
> > +      if (EFI_ERROR (RecoveryStatus)) {
> > +        DEBUG ((EFI_D_ERROR, "XhcPeiBulkTransfer:
> > + XhcPeiRecoverHaltedEndpoint
> > failed\n"));
> > +      }
> > +      Status = EFI_DEVICE_ERROR;
> >      }
> > -    Status = EFI_DEVICE_ERROR;
> >    }
> >
> >    XhcPeiFreeUrb (Xhc, Urb);
> > diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> > b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> > index eedf377..207b328 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> > +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> > @@ -511,6 +511,92 @@ Done:
> >  }
> >
> >  /**
> > +  System software shall use a Stop Endpoint Command (section 4.6.9)
> > + and the Set TR Dequeue Pointer  Command (section 4.6.10) to remove
> > + the timed-out TDs from the xHC transfer ring. The next write to  the
> > + Doorbell of the Endpoint will transition the Endpoint Context from
> > + the Stopped to
> > the Running  state.
> > +
> > +  @param  Xhc                   The XHCI device.
> > +  @param  Urb                   The urb which doesn't get completed in a
> specified timeout
> > range.
> > +
> > +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> > +  @retval Others                Failed to stop the endpoint and dequeue 
> > the TDs.
> > +
> > +**/
> > +EFI_STATUS
> > +XhcPeiDequeueTrbFromEndpoint (
> > +  IN PEI_XHC_DEV        *Xhc,
> > +  IN URB                *Urb
> > +  )
> > +{
> > +  EFI_STATUS                  Status;
> > +  EVT_TRB_COMMAND_COMPLETION  *EvtTrb;
> > +  CMD_TRB_STOP_ENDPOINT       CmdTrbStopED;
> > +  CMD_SET_TR_DEQ_POINTER      CmdSetTRDeq;
> > +  UINT8                       Dci;
> > +  UINT8                       SlotId;
> > +  EFI_PHYSICAL_ADDRESS        PhyAddr;
> > +
> > +  Status = EFI_SUCCESS;
> > +  SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);  if
> > + (SlotId == 0) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +  Dci = XhcPeiEndpointToDci (Urb->Ep.EpAddr, (UINT8)
> > + (Urb->Ep.Direction));
> > +
> > +  DEBUG ((EFI_D_INFO, "XhcPeiDequeueTrbFromEndpoint: Stop Slot =
> %x,
> > + Dci = %x\n", SlotId, Dci));
> > +
> > +  //
> > +  // 1) Send Stop endpoint command to stop endpoint.
> > +  //
> > +  ZeroMem (&CmdTrbStopED, sizeof (CmdTrbStopED));
> > + CmdTrbStopED.CycleBit = 1;
> > +  CmdTrbStopED.Type     = TRB_TYPE_STOP_ENDPOINT;
> > +  CmdTrbStopED.EDID     = Dci;
> > +  CmdTrbStopED.SlotId   = SlotId;
> > +  Status = XhcPeiCmdTransfer (
> > +             Xhc,
> > +             (TRB_TEMPLATE *) (UINTN) &CmdTrbStopED,
> > +             XHC_GENERIC_TIMEOUT,
> > +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> > +             );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG ((EFI_D_ERROR, "XhcPeiDequeueTrbFromEndpoint: Stop
> Endpoint
> > + Failed,
> > Status = %r\n", Status));
> > +    goto Done;
> > +  }
> > +
> > +  //
> > +  // 2) Set dequeue pointer
> > +  //
> > +  ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));  PhyAddr =
> > + UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring-
> >RingEnqueue,
> > + sizeof
> > (CMD_SET_TR_DEQ_POINTER));
> > +  CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring-
> >RingPCS;
> > +  CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
> > +  CmdSetTRDeq.CycleBit = 1;
> > +  CmdSetTRDeq.Type     = TRB_TYPE_SET_TR_DEQUE;
> > +  CmdSetTRDeq.Endpoint = Dci;
> > +  CmdSetTRDeq.SlotId   = SlotId;
> > +  Status = XhcPeiCmdTransfer (
> > +             Xhc,
> > +             (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,
> > +             XHC_GENERIC_TIMEOUT,
> > +             (TRB_TEMPLATE **) (UINTN) &EvtTrb
> > +             );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG ((EFI_D_ERROR, "XhcPeiDequeueTrbFromEndpoint: Set
> Dequeue
> > + Pointer
> > Failed, Status = %r\n", Status));
> > +    goto Done;
> > +  }
> > +
> > +  //
> > +  // 3) Ring the doorbell to transit from stop to active  //
> > + XhcPeiRingDoorBell (Xhc, SlotId, Dci);
> > +
> > +Done:
> > +  return Status;
> > +}
> > +
> > +/**
> >    Check if the Trb is a transaction of the URB.
> >
> >    @param Trb        The TRB to be checked
> > diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> > b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> > index 19672d0..e0e1938 100644
> > --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> > +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >  Private Header file for Usb Host Controller PEIM
> >
> > -Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2014 - 2015, Intel Corporation. All rights
> > +reserved.<BR>
> >
> >  This program and the accompanying materials  are licensed and made
> > available under the terms and conditions @@ -1067,6 +1067,25 @@
> > XhcPeiRecoverHaltedEndpoint (
> >    );
> >
> >  /**
> > +  System software shall use a Stop Endpoint Command (section 4.6.9)
> > + and the Set TR Dequeue Pointer  Command (section 4.6.10) to remove
> > + the timed-out TDs from the xHC transfer ring. The next write to  the
> > + Doorbell of the Endpoint will transition the Endpoint Context from
> > + the Stopped to
> > the Running  state.
> > +
> > +  @param  Xhc                   The XHCI device.
> > +  @param  Urb                   The urb which doesn't get completed in a
> specified timeout
> > range.
> > +
> > +  @retval EFI_SUCCESS           The dequeuing of the TDs is successful.
> > +  @retval Others                Failed to stop the endpoint and dequeue 
> > the TDs.
> > +
> > +**/
> > +EFI_STATUS
> > +XhcPeiDequeueTrbFromEndpoint (
> > +  IN PEI_XHC_DEV        *Xhc,
> > +  IN URB                *Urb
> > +  );
> > +
> > +/**
> >    Create a new URB for a new transaction.
> >
> >    @param  Xhc       The XHCI device
> > --
> > 1.9.5.msysgit.0
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to