From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 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 05A992035A7C8 for ; Thu, 16 Nov 2017 18:32:49 -0800 (PST) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Nov 2017 18:36:59 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,406,1505804400"; d="scan'208";a="174496170" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by orsmga005.jf.intel.com with ESMTP; 16 Nov 2017 18:36:59 -0800 Received: from fmsmsx116.amr.corp.intel.com (10.18.116.20) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 16 Nov 2017 18:36:58 -0800 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by fmsmsx116.amr.corp.intel.com (10.18.116.20) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 16 Nov 2017 18:36:58 -0800 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.152]) by shsmsx102.ccr.corp.intel.com ([169.254.2.175]) with mapi id 14.03.0319.002; Fri, 17 Nov 2017 10:36:56 +0800 From: "Wu, Hao A" To: "Zeng, Star" , "edk2-devel@lists.01.org" CC: "Yao, Jiewen" Thread-Topic: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu Thread-Index: AQHTUfbpfhizG/g5ekOhe4UPejnWvqMWY/CAgAGRC1A= Date: Fri, 17 Nov 2017 02:36:55 +0000 Message-ID: References: <20171031031801.20216-1-hao.a.wu@intel.com> <0C09AFA07DD0434D9E2A0C6AEB0483103B9B6378@shsmsx102.ccr.corp.intel.com> In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B9B6378@shsmsx102.ccr.corp.intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [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: , X-List-Received-Date: Fri, 17 Nov 2017 02:32:50 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable > -----Original Message----- > From: Zeng, Star > Sent: Thursday, November 16, 2017 6:38 PM > To: Wu, Hao A; edk2-devel@lists.01.org > Cc: Wu, Hao A; Yao, Jiewen; Zeng, Star > Subject: RE: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu >=20 > How about calling IoMmuInit () after locating > gEdkiiPeiUfsHostControllerPpiGuid? >=20 > Same comment to SdBlockIoPei and EmmcBlockIoPei. >=20 > If you agree, Reviewed-by: Star Zeng Thanks. I will update the codes according to your comments when I push the changes. Also, for the SD/eMMC patch series, do you still need to review them? Or I can get your R-b with the above-mentioned change? Best Regards, Hao Wu >=20 > Thanks, > Star > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ha= o > Wu > Sent: Tuesday, October 31, 2017 11:18 AM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A ; Yao, Jiewen ; > Zeng, Star > Subject: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu >=20 > V2 changes: > Resource cleanup logic update in UfsEndOfPei(). >=20 > V1 history: > Update the UfsBlockIoPei driver to consume IOMMU_PPI to allocate DMA > buffer. >=20 > If no IOMMU_PPI exists, this driver still calls PEI service to allocate D= MA buffer, > with assumption that DRAM=3D=3DDMA. >=20 > This is a compatible change. >=20 > 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(-) >=20 > 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 IMPLIED. > + > +**/ > + > +#include "UfsBlockIoPei.h" > + > +EDKII_IOMMU_PPI *mIoMmu; > + > +/** > + Provides the controller-specific addresses required to access system > +memory from a > + DMA bus master. > + > + @param Operation Indicates if the bus master is going to = read or > write to system memory. > + @param HostAddress The system memory address to map to the = PCI > controller. > + @param NumberOfBytes On input the number of bytes to map. On > output the number of bytes > + that were mapped. > + @param DeviceAddress The resulting map address for the bus ma= ster > 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 > NumberOfBytes. > + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a > common 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 > requested 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 > by Map(). > + @retval EFI_DEVICE_ERROR The data was not committed to the target > system 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 memor= y > address of the > + allocated range. > + @param DeviceAddress The resulting map address for the bus ma= ster > 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 allocate= d. > + @retval EFI_UNSUPPORTED Attributes is unsupported. The only lega= l > 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_WRIT= E > + ); > + 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 > allocated 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/MdeModulePkg/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_TERMINATE_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 Notif= ication > + event that caused this function to exec= ute. > + @param[in] Ppi Pointer to the PPI data associated with= this > 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 > + (NotifyDescriptor); > + > + 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/MdeModulePkg/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 = BSD > License > which accompanies this distribution. The full text of the license may= be 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_PRIVATE_DATA, BlkIoPpi, UFS_PEIM_HC_SIG) #define > GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, > UFS_PEIM_HC_PRIVATE_DATA, BlkIo2Ppi, UFS_PEIM_HC_SIG) > +#define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, > +UFS_PEIM_HC_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 > +memory from a > + DMA bus master. > + > + @param Operation Indicates if the bus master is going to = read or > write to system memory. > + @param HostAddress The system memory address to map to the = PCI > controller. > + @param NumberOfBytes On input the number of bytes to map. On > output the number of bytes > + that were mapped. > + @param DeviceAddress The resulting map address for the bus ma= ster > 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 > NumberOfBytes. > + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a > common 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 > requested 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 > by Map(). > + @retval EFI_DEVICE_ERROR The data was not committed to the target > system 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 memor= y > address of the > + allocated range. > + @param DeviceAddress The resulting map address for the bus ma= ster > 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 allocate= d. > + @retval EFI_UNSUPPORTED Attributes is unsupported. The only lega= l > 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 > allocated 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 Notif= ication > + event that caused this function to exec= ute. > + @param[in] Ppi Pointer to the PPI data associated with= this > 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/MdeModulePkg/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 BSD 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/Bus/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, > + Block->Mapping); > } >=20 > /** > diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h > b/MdeModulePkg/Bus/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= allocated > UINTN BitsLen; > 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 exe= cuted. > @param[in] Packet The pointer to the UFS_SCSI_REQUEST_PACK= ET > data structure. > @param[in] Trd The pointer to the UTP Transfer Request = Descriptor. > + @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, > + BufferMap); > + > + if (EFI_ERROR (Status) || (MapLength !=3D Length)) { > + DEBUG ((DEBUG_ERROR, "UfsCreateScsiCommandDesc: Fail to map data > buffer.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > } >=20 > PrdtNumber =3D (UINTN)DivU64x32 ((UINT64)Length + > UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD); @@ - > 473,7 +491,7 @@ UfsCreateScsiCommandDesc ( > PrdtBase =3D (UTP_TR_PRD*)(CommandDesc + ROUNDUP8 (sizeof > (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU))); >=20 > UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, > Packet->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, > + &PacketBufferMap); > 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_NUTMRS), 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 > (Nutmrs * sizeof (UTP_TMRD)))); > + ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutmrs > * > + sizeof (UTP_TMRD)))); >=20 > // > // Program the UTP Task Management Request List Base Address and UTP > Task Management > // Request List Base Address with a 64-bit address allocated at step 6= . > // > Address =3D Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET; > - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); > + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); > Address =3D Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET; > - 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 > Management @@ -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 > (Nutrs * sizeof (UTP_TRD)))); > + ZeroMem (CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Nutrs * > + sizeof (UTP_TRD)))); >=20 > // > // Program the UTP Transfer Request List Base Address and UTP Transfer > Request List > // Base Address with a 64-bit address allocated at step 8. > // > Address =3D Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET; > - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); > + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); > Address =3D Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET; > - 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 Re= quest > List @@ -1735,6 +1764,16 @@ UfsControllerInit ( > Status =3D UfsInitTransferRequestList (Private); > if (EFI_ERROR (Status)) { > DEBUG ((EFI_D_ERROR, "UfsDevicePei: Transfer list initialization Fai= ls, > 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 > -- > 2.12.0.windows.1 >=20 > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel