Yes, same comments to SD/eMMC series. Thanks, Star -----Original Message----- From: Wu, Hao A Sent: Friday, November 17, 2017 10:37 AM To: Zeng, Star <star.z...@intel.com>; edk2-devel@lists.01.org Cc: Yao, Jiewen <jiewen....@intel.com> Subject: RE: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu
> -----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 > > How about calling IoMmuInit () after locating > gEdkiiPeiUfsHostControllerPpiGuid? > > Same comment to SdBlockIoPei and EmmcBlockIoPei. > > If you agree, Reviewed-by: Star Zeng <star.z...@intel.com> 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 > > Thanks, > Star > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of > Hao Wu > Sent: Tuesday, October 31, 2017 11:18 AM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a...@intel.com>; Yao, Jiewen > <jiewen....@intel.com>; Zeng, Star <star.z...@intel.com> > Subject: [edk2] [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu > > 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==DMA. > > This is a compatible change. > > Cc: Star Zeng <star.z...@intel.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Hao Wu <hao.a...@intel.com> > --- > 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.<BR> > + > + 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 master > 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 != NULL) { > + Status = mIoMmu->Map ( > + mIoMmu, > + Operation, > + HostAddress, > + NumberOfBytes, > + DeviceAddress, > + Mapping > + ); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + switch (Operation) { > + case EdkiiIoMmuOperationBusMasterRead: > + case EdkiiIoMmuOperationBusMasterRead64: > + Attribute = EDKII_IOMMU_ACCESS_READ; > + break; > + case EdkiiIoMmuOperationBusMasterWrite: > + case EdkiiIoMmuOperationBusMasterWrite64: > + Attribute = EDKII_IOMMU_ACCESS_WRITE; > + break; > + case EdkiiIoMmuOperationBusMasterCommonBuffer: > + case EdkiiIoMmuOperationBusMasterCommonBuffer64: > + Attribute = EDKII_IOMMU_ACCESS_READ | > EDKII_IOMMU_ACCESS_WRITE; > + break; > + default: > + ASSERT(FALSE); > + return EFI_INVALID_PARAMETER; > + } > + Status = mIoMmu->SetAttribute ( > + mIoMmu, > + *Mapping, > + Attribute > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; > + *Mapping = NULL; > + Status = 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 != NULL) { > + Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0); > + Status = mIoMmu->Unmap (mIoMmu, Mapping); > + } else { > + Status = 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 master > 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 = NULL; > + *DeviceAddress = 0; > + > + if (mIoMmu != NULL) { > + Status = mIoMmu->AllocateBuffer ( > + mIoMmu, > + EfiBootServicesData, > + Pages, > + HostAddress, > + 0 > + ); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + NumberOfBytes = EFI_PAGES_TO_SIZE(Pages); > + Status = mIoMmu->Map ( > + mIoMmu, > + EdkiiIoMmuOperationBusMasterCommonBuffer, > + *HostAddress, > + &NumberOfBytes, > + DeviceAddress, > + Mapping > + ); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + Status = mIoMmu->SetAttribute ( > + mIoMmu, > + *Mapping, > + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + Status = PeiServicesAllocatePages ( > + EfiBootServicesData, > + Pages, > + &HostPhyAddress > + ); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + *HostAddress = (VOID *)(UINTN)HostPhyAddress; > + *DeviceAddress = HostPhyAddress; > + *Mapping = 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 != NULL) { > + Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0); > + Status = mIoMmu->Unmap (mIoMmu, Mapping); > + Status = mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress); > + } else { > + Status = 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 = { > 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 ( } > > /** > + 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 > Notification > + event that caused this function to execute. > + @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 = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY > + (NotifyDescriptor); > + > + if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) { > + UfsPeimFreeMemPool (Private->Pool); } > + > + if (Private->UtpTmrlBase != NULL) { > + IoMmuFreeBuffer ( > + EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), > + Private->UtpTmrlBase, > + Private->TmrlMapping > + ); > + } > + > + if (Private->UtpTrlBase != 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. > > @param FileHandle Handle of the file being invoked. > @@ -1093,6 +1148,8 @@ InitializeUfsBlockIoPeim ( > return EFI_SUCCESS; > } > > + IoMmuInit (); > + > // > // locate ufs host controller PPI > // > @@ -1185,7 +1242,8 @@ InitializeUfsBlockIoPeim ( > } > } > > - Status = PeiServicesInstallPpi (&Private->BlkIoPpiList); > + PeiServicesInstallPpi (&Private->BlkIoPpiList); > + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList); > Controller++; > } > > 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 > > - Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2014 - 2017, Intel Corporation. All rights > + reserved.<BR> > 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 <Ppi/UfsHostController.h> > #include <Ppi/BlockIo.h> #include <Ppi/BlockIo2.h> > +#include <Ppi/IoMmu.h> > +#include <Ppi/EndOfPeiPhase.h> > > #include <Library/DebugLib.h> > #include <Library/BaseLib.h> > @@ -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]; > > + // > + // EndOfPei callback is used to stop the UFS DMA operation // > + after exit PEI phase. > + // > + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; > + > UINTN UfsHcBase; > UINT32 Capabilities; > > @@ -119,8 +127,10 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA { > > VOID *UtpTrlBase; > UINT8 Nutrs; > + VOID *TrlMapping; > VOID *UtpTmrlBase; > UINT8 Nutmrs; > + VOID *TmrlMapping; > > UFS_PEIM_EXPOSED_LUNS Luns; > } UFS_PEIM_HC_PRIVATE_DATA; > @@ -133,6 +143,7 @@ typedef struct _UFS_PEIM_HC_PRIVATE_DATA { > > #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) > > #define UFS_SCSI_OP_LENGTH_SIX 0x6 > #define UFS_SCSI_OP_LENGTH_TEN 0xa > @@ -527,6 +538,20 @@ UfsPeimInitMemPool ( > ); > > /** > + 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. > > @@ -557,4 +582,118 @@ UfsPeimFreeMem ( > IN UINTN Size > ); > > +/** > + 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 master > 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 memory > address of the > + allocated range. > + @param DeviceAddress The resulting map address for the bus master > 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 > 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 > Notification > + event that caused this function to execute. > + @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.<BR> > +# Copyright (c) 2014 - 2017, Intel Corporation. All rights > +reserved.<BR> > # > # 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 > > [Packages] > MdePkg/MdePkg.dec > @@ -53,6 +54,8 @@ > gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES > gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES > gEdkiiPeiUfsHostControllerPpiGuid ## CONSUMES > + gEdkiiIoMmuPpiGuid ## CONSUMES > + gEfiEndOfPeiSignalPpiGuid ## CONSUMES > > [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 > > -Copyright (c) 2014 - 2016, Intel Corporation. All rights > reserved.<BR> > +Copyright (c) 2014 - 2017, Intel Corporation. All rights > +reserved.<BR> > > 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; > > TempPtr = NULL; > Block = NULL; > @@ -62,19 +64,22 @@ UfsPeimAllocMemBlock ( > > Block->Bits = (UINT8*)(UINTN)TempPtr; > > - Status = PeiServicesAllocatePages ( > - EfiBootServicesCode, > + Status = IoMmuAllocateBuffer ( > Pages, > - &Address > + &BufHost, > + &MappedAddr, > + &Mapping > ); > if (EFI_ERROR (Status)) { > return NULL; > } > > - ZeroMem ((VOID*)(UINTN)Address, EFI_PAGES_TO_SIZE (Pages)); > + ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages)); > > - Block->Buf = (UINT8*)((UINTN)Address); > - Block->Next = NULL; > + Block->BufHost = (UINT8 *) (UINTN) BufHost; > + Block->Buf = (UINT8 *) (UINTN) MappedAddr; > + Block->Mapping = Mapping; > + Block->Next = NULL; > > return Block; > } > @@ -93,6 +98,8 @@ UfsPeimFreeMemBlock ( > ) > { > ASSERT ((Pool != NULL) && (Block != NULL)); > + > + IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, > + Block->Mapping); > } > > /** > 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 > > -Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2014 - 2017, Intel Corporation. All rights > +reserved.<BR> > > 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; > }; > > 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 > executed. > @param[in] Packet The pointer to the UFS_SCSI_REQUEST_PACKET > 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(). > > @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; > > ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL)); > > + BufferPhyAddr = 0; > + > if (Packet->DataDirection == UfsDataIn) { > - Buffer = Packet->InDataBuffer; > - Length = Packet->InTransferLength; > + Buffer = Packet->InDataBuffer; > + Length = Packet->InTransferLength; > DataDirection = UfsDataIn; > + MapOp = EdkiiIoMmuOperationBusMasterWrite; > } else { > Buffer = Packet->OutDataBuffer; > Length = Packet->OutTransferLength; > DataDirection = UfsDataOut; > + MapOp = EdkiiIoMmuOperationBusMasterRead; > } > > if (Length == 0) { > DataDirection = UfsNoData; > + } else { > + MapLength = Length; > + Status = IoMmuMap (MapOp, Buffer, &MapLength, &BufferPhyAddr, > + BufferMap); > + > + if (EFI_ERROR (Status) || (MapLength != Length)) { > + DEBUG ((DEBUG_ERROR, "UfsCreateScsiCommandDesc: Fail to map > + data > buffer.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > } > > PrdtNumber = (UINTN)DivU64x32 ((UINT64)Length + > UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD); @@ - > 473,7 +491,7 @@ UfsCreateScsiCommandDesc ( > PrdtBase = (UTP_TR_PRD*)(CommandDesc + ROUNDUP8 (sizeof > (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU))); > > UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, > Packet->Cdb, > Packet->CdbLength, DataDirection, Length); > - UfsInitUtpPrdt (PrdtBase, Buffer, Length); > + UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)BufferPhyAddr, Length); > > // > // Fill UTP_TRD associated fields > @@ -1286,6 +1304,7 @@ UfsExecScsiCmds ( > UTP_RESPONSE_UPIU *Response; > UINT16 SenseDataLen; > UINT32 ResTranCount; > + VOID *PacketBufferMap; > > // > // Find out which slot of transfer request list is available. > @@ -1296,11 +1315,12 @@ UfsExecScsiCmds ( > } > > Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot; > + PacketBufferMap = NULL; > > // > // Fill transfer request descriptor to this slot. > // > - Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd); > + Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd, > + &PacketBufferMap); > if (EFI_ERROR (Status)) { > return Status; > } > @@ -1362,6 +1382,9 @@ UfsExecScsiCmds ( > } > > Exit: > + if (PacketBufferMap != NULL) { > + IoMmuUnmap (PacketBufferMap); > + } > UfsStopExecCmd (Private, Slot); > UfsPeimFreeMem (Private->Pool, CmdDescBase, CmdDescSize); > > @@ -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; > > // > @@ -1601,28 +1626,29 @@ UfsInitTaskManagementRequestList ( > // Allocate and initialize UTP Task Management Request List. > // > Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & > UFS_HC_CAP_NUTMRS), 16) + 1); > - Status = PeiServicesAllocatePages ( > - EfiBootServicesCode, > + Status = IoMmuAllocateBuffer ( > EFI_SIZE_TO_PAGES (Nutmrs * sizeof (UTP_TMRD)), > - &Buffer > + &CmdDescHost, > + &CmdDescPhyAddr, > + &CmdDescMapping > ); > - > if (EFI_ERROR (Status)) { > return EFI_DEVICE_ERROR; > } > > - 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)))); > > // > // 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 = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET; > - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); > + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); > Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET; > - MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32)); > - Private->UtpTmrlBase = (VOID*)(UINTN)Buffer; > + MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, > + 32)); Private->UtpTmrlBase = (VOID*)(UINTN)CmdDescHost; > Private->Nutmrs = Nutmrs; > + Private->TmrlMapping = CmdDescMapping; > > // > // 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; > > // > @@ -1665,28 +1693,29 @@ UfsInitTransferRequestList ( > // Allocate and initialize UTP Transfer Request List. > // > Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1); > - Status = PeiServicesAllocatePages ( > - EfiBootServicesCode, > + Status = IoMmuAllocateBuffer ( > EFI_SIZE_TO_PAGES (Nutrs * sizeof (UTP_TRD)), > - &Buffer > + &CmdDescHost, > + &CmdDescPhyAddr, > + &CmdDescMapping > ); > - > if (EFI_ERROR (Status)) { > return EFI_DEVICE_ERROR; > } > > - 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)))); > > // > // 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 = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET; > - MmioWrite32 (Address, (UINT32)(UINTN)Buffer); > + MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); > Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET; > - MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)Buffer, 32)); > - Private->UtpTrlBase = (VOID*)(UINTN)Buffer; > + MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, > + 32)); Private->UtpTrlBase = (VOID*)(UINTN)CmdDescHost; > Private->Nutrs = Nutrs; > + Private->TrlMapping = CmdDescMapping; > > // > // Enable the UTP Transfer Request List by setting the UTP Transfer > Request List @@ -1735,6 +1764,16 @@ UfsControllerInit ( > Status = UfsInitTransferRequestList (Private); > if (EFI_ERROR (Status)) { > DEBUG ((EFI_D_ERROR, "UfsDevicePei: Transfer list initialization > Fails, Status = %r\n", Status)); > + > + if (Private->TmrlMapping != NULL) { > + IoMmuFreeBuffer ( > + EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), > + Private->UtpTmrlBase, > + Private->TmrlMapping > + ); > + Private->TmrlMapping = NULL; > + } > + > return Status; > } > > -- > 2.12.0.windows.1 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel