X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FXhciPei%2FXhcPeim.c;h=57e70701e826dbea37357c41f62aeeb86bfe1241;hb=1f87985ab7958664a84da78095b5892f88acf3f1;hp=9d9f53ebe3df69eff060533990c264306844c043;hpb=d987459f8e0b78831c95188b5b0d712ed6a54c88;p=mirror_edk2.git
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
index 9d9f53ebe3..57e70701e8 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
@@ -2,7 +2,7 @@
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
-Copyright (c) 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -161,7 +161,7 @@ XhcPeiClearOpRegBit (
@param Offset The offset of the operational register.
@param Bit The bit mask of the register to wait for.
@param WaitToSet Wait the bit to set or clear.
- @param Timeout The time to wait before abort (in microsecond, us).
+ @param Timeout The time to wait before abort (in millisecond, ms).
@retval EFI_SUCCESS The bit successfully changed by host controller.
@retval EFI_TIMEOUT The time out occurred.
@@ -176,14 +176,14 @@ XhcPeiWaitOpRegBit (
IN UINT32 Timeout
)
{
- UINT32 Index;
+ UINT64 Index;
- for (Index = 0; Index < Timeout / XHC_POLL_DELAY + 1; Index++) {
+ for (Index = 0; Index < Timeout * XHC_1_MILLISECOND; Index++) {
if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
return EFI_SUCCESS;
}
- MicroSecondDelay (XHC_POLL_DELAY);
+ MicroSecondDelay (XHC_1_MICROSECOND);
}
return EFI_TIMEOUT;
@@ -381,7 +381,7 @@ XhcPeiIsSysError (
Reset the host controller.
@param Xhc The XHCI device.
- @param Timeout Time to wait before abort (in microsecond, us).
+ @param Timeout Time to wait before abort (in millisecond, ms).
@retval EFI_TIMEOUT The transfer failed due to time out.
@retval Others Failed to reset the host.
@@ -407,6 +407,12 @@ XhcPeiResetHC (
}
XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
+ //
+ // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
+ // Otherwise there may have the timeout case happened.
+ // The below is a workaround to solve such problem.
+ //
+ MicroSecondDelay (1000);
Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
ON_EXIT:
DEBUG ((EFI_D_INFO, "XhcPeiResetHC: %r\n", Status));
@@ -648,17 +654,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;
+ }
}
//
@@ -676,7 +693,7 @@ XhcPeiControlTransfer (
// Store a copy of device scriptor as hub device need this info to configure endpoint.
//
CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
- if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {
+ if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {
//
// If it's a usb3.0 device, then its max packet size is a 2^n.
//
@@ -960,14 +977,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);
@@ -1450,7 +1477,7 @@ XhcPeimEntry (
XhcDev->Signature = USB_XHC_DEV_SIGNATURE;
XhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
- XhcDev->CapLength = XhcPeiReadCapRegister (XhcDev, XHC_CAPLENGTH_OFFSET) & 0x0FF;
+ XhcDev->CapLength = (UINT8) (XhcPeiReadCapRegister (XhcDev, XHC_CAPLENGTH_OFFSET) & 0x0FF);
XhcDev->HcSParams1.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS1_OFFSET);
XhcDev->HcSParams2.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS2_OFFSET);
XhcDev->HcCParams.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCCPARAMS_OFFSET);