From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Zeng, Star" <star.zeng@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu
Date: Fri, 17 Nov 2017 02:36:55 +0000 [thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A0931D1E721@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B9B6378@shsmsx102.ccr.corp.intel.com>
> -----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.zeng@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-bounces@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.wu@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Zeng, Star <star.zeng@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.zeng@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Hao Wu <hao.a.wu@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
next prev parent reply other threads:[~2017-11-17 2:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-31 3:18 [PATCH v2] MdeModulePkg/UfsBlockIoPei: Support IoMmu Hao Wu
2017-11-16 10:38 ` Zeng, Star
2017-11-17 2:36 ` Wu, Hao A [this message]
2017-11-17 2:41 ` Zeng, Star
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=B80AF82E9BFB8E4FBD8C89DA810C6A0931D1E721@SHSMSX104.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox