diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c index 373f1bed45..193b0f24e2 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c @@ -7,7 +7,7 @@ It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use. Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. - Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -974,6 +974,58 @@ SdMmcPciHcDriverBindingStop ( return Status; } +/** + Execute TRB synchronously. + + @param[in] Private Pointer to driver private data. + @param[in] Trb Pointer to TRB to execute. + + @retval EFI_SUCCESS TRB executed successfully. + @retval Other TRB failed. +**/ +EFI_STATUS +SdMmcPassThruExecSyncTrb ( + IN SD_MMC_HC_PRIVATE_DATA *Private, + IN SD_MMC_HC_TRB *Trb + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Wait async I/O list is empty before execute sync I/O operation. + // + while (TRUE) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + if (IsListEmpty (&Private->Queue)) { + gBS->RestoreTPL (OldTpl); + break; + } + gBS->RestoreTPL (OldTpl); + } + + while (Trb->Retries) { + Status = SdMmcWaitTrbEnv (Private, Trb); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SdMmcExecTrb (Private, Trb); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SdMmcWaitTrbResult (Private, Trb); + if (Status == EFI_CRC_ERROR) { + Trb->Retries--; + } else { + return Status; + } + } + + return Status; +} + /** Sends SD command to an SD card that is attached to the SD controller. @@ -1023,7 +1075,6 @@ SdMmcPassThruPassThru ( EFI_STATUS Status; SD_MMC_HC_PRIVATE_DATA *Private; SD_MMC_HC_TRB *Trb; - EFI_TPL OldTpl; if ((This == NULL) || (Packet == NULL)) { return EFI_INVALID_PARAMETER; @@ -1066,34 +1117,8 @@ SdMmcPassThruPassThru ( return EFI_SUCCESS; } - // - // Wait async I/O list is empty before execute sync I/O operation. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - if (IsListEmpty (&Private->Queue)) { - gBS->RestoreTPL (OldTpl); - break; - } - gBS->RestoreTPL (OldTpl); - } + Status = SdMmcPassThruExecSyncTrb (Private, Trb); - Status = SdMmcWaitTrbEnv (Private, Trb); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = SdMmcExecTrb (Private, Trb); - if (EFI_ERROR (Status)) { - goto Done; - } - - Status = SdMmcWaitTrbResult (Private, Trb); - if (EFI_ERROR (Status)) { - goto Done; - } - -Done: SdMmcFreeTrb (Trb); return Status; diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h index 0304960132..5bc3577ba2 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h @@ -3,7 +3,7 @@ Provides some data structure definitions used by the SD/MMC host controller driver. Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -130,6 +130,8 @@ typedef struct { #define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T') +#define SD_MMC_TRB_RETRIES 5 + // // TRB (Transfer Request Block) contains information for the cmd request. // @@ -152,6 +154,7 @@ typedef struct { EFI_EVENT Event; BOOLEAN Started; UINT64 Timeout; + UINT32 Retries; SD_MMC_HC_ADMA_32_DESC_LINE *Adma32Desc; SD_MMC_HC_ADMA_64_V3_DESC_LINE *Adma64V3Desc; diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 85c97c1f27..b05c818462 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -1683,6 +1683,7 @@ SdMmcCreateTrb ( Trb->Event = Event; Trb->Started = FALSE; Trb->Timeout = Packet->Timeout; + Trb->Retries = SD_MMC_TRB_RETRIES; Trb->Private = Private; if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {