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