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);