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.tian@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Baraneedharan Anbazhagan <anbazhagan@hp.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18313 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user