From nobody Wed Dec 25 01:04:12 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1509419895406444.5103252427871; Mon, 30 Oct 2017 20:18:15 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 0CC802034AB1E; Mon, 30 Oct 2017 20:14:22 -0700 (PDT) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 71F332034AB08 for ; Mon, 30 Oct 2017 20:14:19 -0700 (PDT) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Oct 2017 20:18:09 -0700 Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.13]) by fmsmga004.fm.intel.com with ESMTP; 30 Oct 2017 20:18:08 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.88; helo=mga01.intel.com; envelope-from=hao.a.wu@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,322,1505804400"; d="scan'208";a="329884308" From: Hao Wu To: edk2-devel@lists.01.org Date: Tue, 31 Oct 2017 11:18:01 +0800 Message-Id: <20171031031801.20216-1-hao.a.wu@intel.com> X-Mailer: git-send-email 2.12.0.windows.1 Subject: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hao Wu , Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" V2 changes: Resource cleanup logic update in UfsEndOfPei(). V1 history: Update the UfsBlockIoPei driver to consume IOMMU_PPI to allocate DMA buffer. If no IOMMU_PPI exists, this driver still calls PEI service to allocate DMA buffer, with assumption that DRAM=3D=3DDMA. This is a compatible change. Cc: Star Zeng Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu --- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/DmaMem.c | 249 +++++++++++++++= +++++ MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c | 60 ++++- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h | 141 ++++++++++- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf | 5 +- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c | 23 +- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h | 4 +- MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c | 91 +++++-- 7 files changed, 535 insertions(+), 38 deletions(-) diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/DmaMem.c b/MdeModulePkg/Bus= /Ufs/UfsBlockIoPei/DmaMem.c new file mode 100644 index 0000000000..0a939a3879 --- /dev/null +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/DmaMem.c @@ -0,0 +1,249 @@ +/** @file + The DMA memory help function. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "UfsBlockIoPei.h" + +EDKII_IOMMU_PPI *mIoMmu; + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->Map ( + mIoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute =3D EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute =3D EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + *Mapping =3D NULL; + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + + *HostAddress =3D NULL; + *DeviceAddress =3D 0; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->AllocateBuffer ( + mIoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes =3D EFI_PAGES_TO_SIZE(Pages); + Status =3D mIoMmu->Map ( + mIoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status =3D PeiServicesAllocatePages ( + EfiBootServicesData, + Pages, + &HostPhyAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + *HostAddress =3D (VOID *)(UINTN)HostPhyAddress; + *DeviceAddress =3D HostPhyAddress; + *Mapping =3D NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress = and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + Status =3D mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ) +{ + PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **)&mIoMmu + ); +} + diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c b/MdeModule= Pkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c index ddeee3e1bc..f030880a85 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c @@ -107,13 +107,20 @@ UFS_PEIM_HC_PRIVATE_DATA gUfsHcPeimTemplate =3D { 0 } }, + { // EndOfPeiNotifyList + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMI= NATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + UfsEndOfPei + }, 0, // UfsHcBase 0, // Capabilities 0, // TaskTag 0, // UtpTrlBase 0, // Nutrs + NULL, // TrlMapping 0, // UtpTmrlBase 0, // Nutmrs + NULL, // TmrlMapping { // Luns { UFS_LUN_0, // Ufs Common Lun 0 @@ -1062,6 +1069,54 @@ UfsBlockIoPeimReadBlocks2 ( } =20 /** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +UfsEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + UFS_PEIM_HC_PRIVATE_DATA *Private; + + Private =3D GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescrip= tor); + + if ((Private->Pool !=3D NULL) && (Private->Pool->Head !=3D NULL)) { + UfsPeimFreeMemPool (Private->Pool); + } + + if (Private->UtpTmrlBase !=3D NULL) { + IoMmuFreeBuffer ( + EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), + Private->UtpTmrlBase, + Private->TmrlMapping + ); + } + + if (Private->UtpTrlBase !=3D NULL) { + IoMmuFreeBuffer ( + EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TRD)), + Private->UtpTrlBase, + Private->TrlMapping + ); + } + + UfsControllerStop (Private); + + return EFI_SUCCESS; +} + +/** The user code starts with this function. =20 @param FileHandle Handle of the file being invoked. @@ -1093,6 +1148,8 @@ InitializeUfsBlockIoPeim ( return EFI_SUCCESS; } =20 + IoMmuInit (); + // // locate ufs host controller PPI // @@ -1185,7 +1242,8 @@ InitializeUfsBlockIoPeim ( } } =20 - Status =3D PeiServicesInstallPpi (&Private->BlkIoPpiList); + PeiServicesInstallPpi (&Private->BlkIoPpiList); + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList); Controller++; } =20 diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h b/MdeModule= Pkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h index 46e9bfe03f..345947c6b1 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -19,6 +19,8 @@ #include #include #include +#include +#include =20 #include #include @@ -112,6 +114,12 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA { EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList; EFI_PEI_BLOCK_IO2_MEDIA Media[UFS_PEIM_MAX_LUNS]; =20 + // + // EndOfPei callback is used to stop the UFS DMA operation + // after exit PEI phase. + // + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; + UINTN UfsHcBase; UINT32 Capabilities; =20 @@ -119,8 +127,10 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA { =20 VOID *UtpTrlBase; UINT8 Nutrs; + VOID *TrlMapping; VOID *UtpTmrlBase; UINT8 Nutmrs; + VOID *TmrlMapping; =20 UFS_PEIM_EXPOSED_LUNS Luns; } UFS_PEIM_HC_PRIVATE_DATA; @@ -133,6 +143,7 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA { =20 #define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, UFS_PEIM_HC_PRIVA= TE_DATA, BlkIoPpi, UFS_PEIM_HC_SIG) #define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, UFS_PEIM_HC_PRIV= ATE_DATA, BlkIo2Ppi, UFS_PEIM_HC_SIG) +#define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, UFS_PEIM_H= C_PRIVATE_DATA, EndOfPeiNotifyList, UFS_PEIM_HC_SIG) =20 #define UFS_SCSI_OP_LENGTH_SIX 0x6 #define UFS_SCSI_OP_LENGTH_TEN 0xa @@ -527,6 +538,20 @@ UfsPeimInitMemPool ( ); =20 /** + Release the memory management pool. + + @param Pool The memory pool to free. + + @retval EFI_DEVICE_ERROR Fail to free the memory pool. + @retval EFI_SUCCESS The memory pool is freed. + +**/ +EFI_STATUS +UfsPeimFreeMemPool ( + IN UFS_PEIM_MEM_POOL *Pool + ); + +/** Allocate some memory from the host controller's memory pool which can be used to communicate with host controller. =20 @@ -557,4 +582,118 @@ UfsPeimFreeMem ( IN UINTN Size ); =20 +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ); + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress = and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ); + +/** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +UfsEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + #endif diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf b/MdeModu= lePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf index 80fe0392b9..28daf67ffc 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf @@ -1,7 +1,7 @@ ## @file # Description file for the Universal Flash Storage (UFS) Peim driver. # -# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License @@ -36,6 +36,7 @@ UfsHci.h UfsHcMem.c UfsHcMem.h + DmaMem.c =20 [Packages] MdePkg/MdePkg.dec @@ -53,6 +54,8 @@ gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES gEdkiiPeiUfsHostControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 [Depex] gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiUfsHostControllerPpiGuid diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c b/MdeModulePkg/B= us/Ufs/UfsBlockIoPei/UfsHcMem.c index bf4079a408..b9e3859b35 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -29,9 +29,11 @@ UfsPeimAllocMemBlock ( ) { UFS_PEIM_MEM_BLOCK *Block; + VOID *BufHost; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS MappedAddr; EFI_STATUS Status; VOID *TempPtr; - EFI_PHYSICAL_ADDRESS Address; =20 TempPtr =3D NULL; Block =3D NULL; @@ -62,19 +64,22 @@ UfsPeimAllocMemBlock ( =20 Block->Bits =3D (UINT8*)(UINTN)TempPtr; =20 - Status =3D PeiServicesAllocatePages ( - EfiBootServicesCode, + Status =3D IoMmuAllocateBuffer ( Pages, - &Address + &BufHost, + &MappedAddr, + &Mapping ); if (EFI_ERROR (Status)) { return NULL; } =20 - ZeroMem ((VOID*)(UINTN)Address, EFI_PAGES_TO_SIZE (Pages)); + ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages)); =20 - Block->Buf =3D (UINT8*)((UINTN)Address); - Block->Next =3D NULL; + Block->BufHost =3D (UINT8 *) (UINTN) BufHost; + Block->Buf =3D (UINT8 *) (UINTN) MappedAddr; + Block->Mapping =3D Mapping; + Block->Next =3D NULL; =20 return Block; } @@ -93,6 +98,8 @@ UfsPeimFreeMemBlock ( ) { ASSERT ((Pool !=3D NULL) && (Block !=3D NULL)); + + IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Bloc= k->Mapping); } =20 /** diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h b/MdeModulePkg/B= us/Ufs/UfsBlockIoPei/UfsHcMem.h index 3c4b2407c8..60db079721 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -27,7 +27,9 @@ struct _UFS_PEIM_MEM_BLOCK { UINT8 *Bits; // Bit array to record which unit is a= llocated UINTN BitsLen;=20 UINT8 *Buf; + UINT8 *BufHost; UINTN BufLen; // Memory size in bytes + VOID *Mapping; UFS_PEIM_MEM_BLOCK *Next; }; =20 diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c b/MdeModulePkg/Bus= /Ufs/UfsBlockIoPei/UfsHci.c index 9c72c1dede..55c7806279 100644 --- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c +++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c @@ -422,6 +422,7 @@ UfsInitQueryRequestUpiu ( @param[in] Lun The Lun on which the SCSI command is execu= ted. @param[in] Packet The pointer to the UFS_SCSI_REQUEST_PACKET= data structure. @param[in] Trd The pointer to the UTP Transfer Request De= scriptor. + @param[out] BufferMap A resulting value, if not NULL, to pass to= IoMmuUnmap(). =20 @retval EFI_SUCCESS The creation succeed. @retval EFI_DEVICE_ERROR The creation failed. @@ -430,10 +431,11 @@ UfsInitQueryRequestUpiu ( **/ EFI_STATUS UfsCreateScsiCommandDesc ( - IN UFS_PEIM_HC_PRIVATE_DATA *Private, - IN UINT8 Lun, - IN UFS_SCSI_REQUEST_PACKET *Packet, - IN UTP_TRD *Trd + IN UFS_PEIM_HC_PRIVATE_DATA *Private, + IN UINT8 Lun, + IN UFS_SCSI_REQUEST_PACKET *Packet, + IN UTP_TRD *Trd, + OUT VOID **BufferMap ) { UINT8 *CommandDesc; @@ -444,21 +446,37 @@ UfsCreateScsiCommandDesc ( UTP_COMMAND_UPIU *CommandUpiu; UTP_TR_PRD *PrdtBase; UFS_DATA_DIRECTION DataDirection; + EFI_STATUS Status; + EDKII_IOMMU_OPERATION MapOp; + UINTN MapLength; + EFI_PHYSICAL_ADDRESS BufferPhyAddr; =20 ASSERT ((Private !=3D NULL) && (Packet !=3D NULL) && (Trd !=3D NULL)); =20 + BufferPhyAddr =3D 0; + if (Packet->DataDirection =3D=3D UfsDataIn) { - Buffer =3D Packet->InDataBuffer; - Length =3D Packet->InTransferLength; + Buffer =3D Packet->InDataBuffer; + Length =3D Packet->InTransferLength; DataDirection =3D UfsDataIn; + MapOp =3D EdkiiIoMmuOperationBusMasterWrite; } else { Buffer =3D Packet->OutDataBuffer; Length =3D Packet->OutTransferLength; DataDirection =3D UfsDataOut; + MapOp =3D EdkiiIoMmuOperationBusMasterRead; } =20 if (Length =3D=3D 0) { DataDirection =3D UfsNoData; + } else { + MapLength =3D Length; + Status =3D IoMmuMap (MapOp, Buffer, &MapLength, &BufferPhyAddr, Buffer= Map); + + if (EFI_ERROR (Status) || (MapLength !=3D Length)) { + DEBUG ((DEBUG_ERROR, "UfsCreateScsiCommandDesc: Fail to map data buf= fer.\n")); + return EFI_OUT_OF_RESOURCES; + } } =20 PrdtNumber =3D (UINTN)DivU64x32 ((UINT64)Length + UFS_MAX_DATA_LEN_PER_P= RD - 1, UFS_MAX_DATA_LEN_PER_PRD); @@ -473,7 +491,7 @@ UfsCreateScsiCommandDesc ( PrdtBase =3D (UTP_TR_PRD*)(CommandDesc + ROUNDUP8 (sizeof (UTP_COMMA= ND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU))); =20 UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, P= acket->CdbLength, DataDirection, Length); - UfsInitUtpPrdt (PrdtBase, Buffer, Length); + UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)BufferPhyAddr, Length); =20 // // Fill UTP_TRD associated fields @@ -1286,6 +1304,7 @@ UfsExecScsiCmds ( UTP_RESPONSE_UPIU *Response; UINT16 SenseDataLen; UINT32 ResTranCount; + VOID *PacketBufferMap; =20 // // Find out which slot of transfer request list is available. @@ -1296,11 +1315,12 @@ UfsExecScsiCmds ( } =20 Trd =3D ((UTP_TRD*)Private->UtpTrlBase) + Slot; + PacketBufferMap =3D NULL; =20 // // Fill transfer request descriptor to this slot. // - Status =3D UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd); + Status =3D UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd, &PacketB= ufferMap); if (EFI_ERROR (Status)) { return Status; } @@ -1362,6 +1382,9 @@ UfsExecScsiCmds ( } =20 Exit: + if (PacketBufferMap !=3D NULL) { + IoMmuUnmap (PacketBufferMap); + } UfsStopExecCmd (Private, Slot); UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize); =20 @@ -1587,7 +1610,9 @@ UfsInitTaskManagementRequestList ( UINTN Address; UINT32 Data; UINT8 Nutmrs; - EFI_PHYSICAL_ADDRESS Buffer; + VOID *CmdDescHost; + EFI_PHYSICAL_ADDRESS CmdDescPhyAddr; + VOID *CmdDescMapping; EFI_STATUS Status; =20 // @@ -1601,28 +1626,29 @@ UfsInitTaskManagementRequestList ( // Allocate and initialize UTP Task Management Request List. // Nutmrs =3D (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMR= S), 16) + 1); - Status =3D PeiServicesAllocatePages ( - EfiBootServicesCode, + Status =3D IoMmuAllocateBuffer ( EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD)), - &Buffer + &CmdDescHost, + &CmdDescPhyAddr, + &CmdDescMapping ); - if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } =20 - ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nut= mrs * sizeof (UTP_TMRD)))); + ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs * siz= eof (UTP_TMRD)))); =20 // // Program the UTP Task Management Request List Base Address and UTP Tas= k Management // Request List Base Address with a 64-bit address allocated at step 6. // Address =3D Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET; =20 - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); Address =3D Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET; =20 - MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32)); - Private->UtpTmrlBase =3D (VOID*)(UINTN)Buffer; + MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32)); + Private->UtpTmrlBase =3D (VOID*)(UINTN)CmdDescHost; Private->Nutmrs =3D Nutmrs; + Private->TmrlMapping =3D CmdDescMapping; =20 // // Enable the UTP Task Management Request List by setting the UTP Task M= anagement @@ -1651,7 +1677,9 @@ UfsInitTransferRequestList ( UINTN Address; UINT32 Data; UINT8 Nutrs; - EFI_PHYSICAL_ADDRESS Buffer; + VOID *CmdDescHost; + EFI_PHYSICAL_ADDRESS CmdDescPhyAddr; + VOID *CmdDescMapping; EFI_STATUS Status; =20 // @@ -1665,28 +1693,29 @@ UfsInitTransferRequestList ( // Allocate and initialize UTP Transfer Request List. // Nutrs =3D (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1); - Status =3D PeiServicesAllocatePages ( - EfiBootServicesCode, + Status =3D IoMmuAllocateBuffer ( EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD)), - &Buffer + &CmdDescHost, + &CmdDescPhyAddr, + &CmdDescMapping ); - if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } =20 - ZeroMem ((VOID*)(UINTN)Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nut= rs * sizeof (UTP_TRD)))); + ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * size= of (UTP_TRD)))); =20 // // Program the UTP Transfer Request List Base Address and UTP Transfer R= equest List // Base Address with a 64-bit address allocated at step 8. // Address =3D Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET; =20 - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); Address =3D Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET; =20 - MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32)); - Private->UtpTrlBase =3D (VOID*)(UINTN)Buffer; + MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32)); + Private->UtpTrlBase =3D (VOID*)(UINTN)CmdDescHost; Private->Nutrs =3D Nutrs; + Private->TrlMapping =3D CmdDescMapping; =20 // // Enable the UTP Transfer Request List by setting the UTP Transfer Requ= est List @@ -1735,6 +1764,16 @@ UfsControllerInit ( Status =3D UfsInitTransferRequestList (Private); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UfsDevicePei: Transfer list initialization Fails= , Status =3D %r\n", Status)); + + if (Private->TmrlMapping !=3D NULL) { + IoMmuFreeBuffer ( + EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), + Private->UtpTmrlBase, + Private->TmrlMapping + ); + Private->TmrlMapping =3D NULL; + } + return Status; } =20 --=20 2.12.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel