MdeModulePkg/XhciDxe: Check timeout URB again after stopping endpoint

This fixes BULK data loss when transfer is detected as timeout but
finished just before stopping endpoint.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
This commit is contained in:
Ruiyu Ni
2017-07-03 17:53:49 +08:00
parent 41fb8ce939
commit 49be9c3c20
4 changed files with 90 additions and 29 deletions

View File

@ -780,26 +780,32 @@ XhcTransfer (
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
*TransferResult = Urb->Result;
*DataLength = Urb->Completed;
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((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed\n", Type));
}
} else {
if (*TransferResult == EFI_USB_NOERROR) {
RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
if (RecoveryStatus == EFI_ALREADY_STARTED) {
//
// The URB is finished just before stopping endpoint.
// Change returning status from EFI_TIMEOUT to EFI_SUCCESS.
//
ASSERT (Urb->Result == EFI_USB_NOERROR);
Status = EFI_SUCCESS;
} else if (*TransferResult == EFI_USB_ERR_STALL) {
RecoveryStatus = XhcRecoverHaltedEndpoint (Xhc, Urb);
if (EFI_ERROR (RecoveryStatus)) {
DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed\n", Type));
}
Status = EFI_DEVICE_ERROR;
DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: pending URB is finished, Length = %d.\n", Type, Urb->Completed));
} else if (EFI_ERROR(RecoveryStatus)) {
DEBUG((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type));
}
}
*TransferResult = Urb->Result;
*DataLength = Urb->Completed;
if (*TransferResult == EFI_USB_ERR_STALL) {
ASSERT (Status == EFI_DEVICE_ERROR);
RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
if (EFI_ERROR (RecoveryStatus)) {
DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed!\n", Type));
}
}