From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.20; helo=mga02.intel.com; envelope-from=jiewen.yao@intel.com; receiver=edk2-devel@lists.01.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (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 54F7F2035A7C8 for ; Thu, 16 Nov 2017 18:28:49 -0800 (PST) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Nov 2017 18:32:59 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,406,1505804400"; d="scan'208";a="174495275" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by orsmga005.jf.intel.com with ESMTP; 16 Nov 2017 18:32:59 -0800 Received: from fmsmsx123.amr.corp.intel.com (10.18.125.38) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 16 Nov 2017 18:32:58 -0800 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by fmsmsx123.amr.corp.intel.com (10.18.125.38) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 16 Nov 2017 18:32:58 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.175]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.213]) with mapi id 14.03.0319.002; Fri, 17 Nov 2017 10:32:57 +0800 From: "Yao, Jiewen" To: "Zeng, Star" , "edk2-devel@lists.01.org" Thread-Topic: [PATCH V2] MdeModulePkg EhciPei: Support IoMmu Thread-Index: AQHTXsIwzvgO4kK+kkqn7JjuGarNQKMX2yww Date: Fri, 17 Nov 2017 02:32:57 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AA2106E@shsmsx102.ccr.corp.intel.com> References: <1510826608-93304-1-git-send-email-star.zeng@intel.com> In-Reply-To: <1510826608-93304-1-git-send-email-star.zeng@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYzhmMmRkNjAtMjFiNy00YzFkLTg4OTItM2NkNTQ1OGI1NzhiIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJKTkZLRk9yTnc1a0JlR3dkSVBNcW16NEpBSGI2SmRsYjFZU1dSWEZXSExzWjdnekplclB4SWdpNFNCZm1RV201In0= x-ctpclassification: CTP_IC dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH V2] MdeModulePkg EhciPei: 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:28:49 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Jiewen.yao@intel.com > -----Original Message----- > From: Zeng, Star > Sent: Thursday, November 16, 2017 6:03 PM > To: edk2-devel@lists.01.org > Cc: Zeng, Star ; Yao, Jiewen > Subject: [PATCH V2] MdeModulePkg EhciPei: Support IoMmu >=20 > V2: Halt HC at EndOfPei. >=20 > Update the EhciPei driver to consume IOMMU_PPI to allocate DMA buffer. >=20 > If no IOMMU_PPI exists, this driver still calls PEI service to allocate > DMA buffer, with assumption that DRAM=3D=3DDMA. >=20 > Cc: Jiewen Yao > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Star Zeng > --- > MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c | 250 > +++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c | 40 ++++- > MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h | 119 ++++++++++++++- > MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf | 6 +- > MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c | 38 +++-- > MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c | 42 ++++-- > MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c | 84 +++++++++-- > MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h | 18 ++- > 8 files changed, 551 insertions(+), 46 deletions(-) > create mode 100644 MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c >=20 > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c > b/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c > new file mode 100644 > index 000000000000..1330f53f411a > --- /dev/null > +++ b/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c > @@ -0,0 +1,250 @@ > +/** @file > +The DMA memory help functions. > + > +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 "EhcPeim.h" > + > +/** > + Provides the controller-specific addresses required to access system m= emory > from a > + DMA bus master. > + > + @param IoMmu Pointer to IOMMU PPI. > + @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_PPI *IoMmu, > + 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 (IoMmu !=3D NULL) { > + Status =3D IoMmu->Map ( > + IoMmu, > + 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 IoMmu->SetAttribute ( > + IoMmu, > + *Mapping, > + Attribute > + ); > + if (EFI_ERROR (Status)) { > + IoMmu->Unmap (IoMmu, Mapping); > + *Mapping =3D NULL; > + 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 IoMmu Pointer to IOMMU PPI. > + @param Mapping The mapping value returned from Map(). > + > +**/ > +VOID > +IoMmuUnmap ( > + IN EDKII_IOMMU_PPI *IoMmu, > + IN VOID *Mapping > + ) > +{ > + if (IoMmu !=3D NULL) { > + IoMmu->SetAttribute (IoMmu, Mapping, 0); > + IoMmu->Unmap (IoMmu, Mapping); > + } > +} > + > +/** > + Allocates pages that are suitable for an OperationBusMasterCommonBuffe= r > or > + OperationBusMasterCommonBuffer64 mapping. > + > + @param IoMmu Pointer to IOMMU PPI. > + @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 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 EDKII_IOMMU_PPI *IoMmu, > + 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; > + *Mapping =3D NULL; > + > + if (IoMmu !=3D NULL) { > + Status =3D IoMmu->AllocateBuffer ( > + IoMmu, > + EfiBootServicesData, > + Pages, > + HostAddress, > + 0 > + ); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + NumberOfBytes =3D EFI_PAGES_TO_SIZE (Pages); > + Status =3D IoMmu->Map ( > + IoMmu, > + EdkiiIoMmuOperationBusMasterCommonBuffer, > + *HostAddress, > + &NumberOfBytes, > + DeviceAddress, > + Mapping > + ); > + if (EFI_ERROR (Status)) { > + IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress); > + *HostAddress =3D NULL; > + return EFI_OUT_OF_RESOURCES; > + } > + Status =3D IoMmu->SetAttribute ( > + IoMmu, > + *Mapping, > + EDKII_IOMMU_ACCESS_READ | > EDKII_IOMMU_ACCESS_WRITE > + ); > + if (EFI_ERROR (Status)) { > + IoMmu->Unmap (IoMmu, *Mapping); > + IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress); > + *Mapping =3D NULL; > + *HostAddress =3D NULL; > + return Status; > + } > + } else { > + Status =3D PeiServicesAllocatePages ( > + EfiBootServicesCode, > + 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 IoMmu Pointer to IOMMU PPI. > + @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(). > + > +**/ > +VOID > +IoMmuFreeBuffer ( > + IN EDKII_IOMMU_PPI *IoMmu, > + IN UINTN Pages, > + IN VOID *HostAddress, > + IN VOID *Mapping > + ) > +{ > + if (IoMmu !=3D NULL) { > + IoMmu->SetAttribute (IoMmu, Mapping, 0); > + IoMmu->Unmap (IoMmu, Mapping); > + IoMmu->FreeBuffer (IoMmu, Pages, HostAddress); > + } > +} > + > +/** > + Initialize IOMMU. > + > + @param IoMmu Pointer to pointer to IOMMU PPI. > + > +**/ > +VOID > +IoMmuInit ( > + OUT EDKII_IOMMU_PPI **IoMmu > + ) > +{ > + PeiServicesLocatePpi ( > + &gEdkiiIoMmuPpiGuid, > + 0, > + NULL, > + (VOID **) IoMmu > + ); > +} > + > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c > b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c > index 31647ff0525c..5cad25e926c5 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c > +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c > @@ -2,7 +2,7 @@ > PEIM to produce gPeiUsb2HostControllerPpiGuid based on > gPeiUsbControllerPpiGuid > which is used to enable recovery function from USB Drivers. >=20 > -Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -1141,6 +1141,36 @@ ON_EXIT: > } >=20 > /** > + One notified function to stop the Host Controller 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 > + @retval others > +**/ > +EFI_STATUS > +EFIAPI > +EhcEndOfPei ( > + IN EFI_PEI_SERVICES **PeiServices, > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, > + IN VOID *Ppi > + ) > +{ > + PEI_USB2_HC_DEV *Ehc; > + > + Ehc =3D PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY > (NotifyDescriptor); > + > + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); > + > + EhcFreeSched (Ehc); > + > + return EFI_SUCCESS; > +} > + > +/** > @param FileHandle Handle of the file being invoked. > @param PeiServices Describes the list of possible PEI Services. >=20 > @@ -1219,6 +1249,8 @@ EhcPeimEntry ( >=20 > EhcDev->Signature =3D USB2_HC_DEV_SIGNATURE; >=20 > + IoMmuInit (&EhcDev->IoMmu); > + > EhcDev->UsbHostControllerBaseAddress =3D (UINT32) BaseAddress; >=20 >=20 > @@ -1250,6 +1282,12 @@ EhcPeimEntry ( > continue; > } >=20 > + EhcDev->EndOfPeiNotifyList.Flags =3D > (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); > + EhcDev->EndOfPeiNotifyList.Guid =3D &gEfiEndOfPeiSignalPpiGuid; > + EhcDev->EndOfPeiNotifyList.Notify =3D EhcEndOfPei; > + > + PeiServicesNotifyPpi (&EhcDev->EndOfPeiNotifyList); > + > Index++; > } >=20 > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h > b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h > index d7a68d909547..279407475b66 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h > +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h > @@ -1,7 +1,7 @@ > /** @file > Private Header file for Usb Host Controller PEIM >=20 > -Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -21,6 +21,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, > EITHER EXPRESS OR IMPLIED. >=20 > #include > #include > +#include > +#include >=20 > #include > #include > @@ -94,7 +96,13 @@ typedef struct _PEI_USB2_HC_DEV PEI_USB2_HC_DEV; > struct _PEI_USB2_HC_DEV { > UINTN Signature; > PEI_USB2_HOST_CONTROLLER_PPI Usb2HostControllerPpi; > - EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; > + EDKII_IOMMU_PPI *IoMmu; > + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; > + // > + // EndOfPei callback is used to stop the XHC DMA operation > + // after exit PEI phase. > + // > + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; > UINT32 UsbHostControllerBaseAddress; > PEI_URB *Urb; > USBHC_MEM_POOL *MemPool; > @@ -122,7 +130,6 @@ struct _PEI_USB2_HC_DEV { > // Periodic (interrupt) transfer schedule data: > // > VOID *PeriodFrame; // Mapped as > common buffer > - VOID *PeriodFrameHost; > VOID *PeriodFrameMap; >=20 > PEI_EHC_QH *PeriodOne; > @@ -138,6 +145,7 @@ struct _PEI_USB2_HC_DEV { > }; >=20 > #define PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(a) CR (a, > PEI_USB2_HC_DEV, Usb2HostControllerPpi, USB2_HC_DEV_SIGNATURE) > +#define PEI_RECOVERY_USB_EHC_DEV_FROM_THIS_NOTIFY(a) CR (a, > PEI_USB2_HC_DEV, EndOfPeiNotifyList, USB2_HC_DEV_SIGNATURE) >=20 > /** > @param EhcDev EHCI Device. > @@ -173,7 +181,8 @@ UsbHcInitMemPool ( >=20 > /** > Release the memory management pool. > - > + > + @param Ehc The EHCI device. > @param Pool The USB memory pool to free. >=20 > @retval EFI_DEVICE_ERROR Fail to free the memory pool. > @@ -182,6 +191,7 @@ UsbHcInitMemPool ( > **/ > EFI_STATUS > UsbHcFreeMemPool ( > + IN PEI_USB2_HC_DEV *Ehc, > IN USBHC_MEM_POOL *Pool > ) > ; > @@ -208,6 +218,7 @@ UsbHcAllocateMem ( > /** > Free the allocated memory back to the memory pool. >=20 > + @param Ehc The EHCI device. > @param Pool The memory pool of the host controller. > @param Mem The memory to free. > @param Size The size of the memory to free. > @@ -215,10 +226,110 @@ UsbHcAllocateMem ( > **/ > VOID > UsbHcFreeMem ( > + IN PEI_USB2_HC_DEV *Ehc, > IN USBHC_MEM_POOL *Pool, > IN VOID *Mem, > IN UINTN Size > ) > ; >=20 > +/** > + Provides the controller-specific addresses required to access system m= emory > from a > + DMA bus master. > + > + @param IoMmu Pointer to IOMMU PPI. > + @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_PPI *IoMmu, > + 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 IoMmu Pointer to IOMMU PPI. > + @param Mapping The mapping value returned from Map(). > + > +**/ > +VOID > +IoMmuUnmap ( > + IN EDKII_IOMMU_PPI *IoMmu, > + IN VOID *Mapping > + ); > + > +/** > + Allocates pages that are suitable for an OperationBusMasterCommonBuffe= r > or > + OperationBusMasterCommonBuffer64 mapping. > + > + @param IoMmu Pointer to IOMMU PPI. > + @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 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 EDKII_IOMMU_PPI *IoMmu, > + IN UINTN Pages, > + OUT VOID **HostAddress, > + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, > + OUT VOID **Mapping > + ); > + > +/** > + Frees memory that was allocated with AllocateBuffer(). > + > + @param IoMmu Pointer to IOMMU PPI. > + @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(). > + > +**/ > +VOID > +IoMmuFreeBuffer ( > + IN EDKII_IOMMU_PPI *IoMmu, > + IN UINTN Pages, > + IN VOID *HostAddress, > + IN VOID *Mapping > + ); > + > +/** > + Initialize IOMMU. > + > + @param IoMmu Pointer to pointer to IOMMU PPI. > + > +**/ > +VOID > +IoMmuInit ( > + OUT EDKII_IOMMU_PPI **IoMmu > + ); > + > #endif > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf > b/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf > index 7083f8668150..813ccc94507d 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf > +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf > @@ -4,7 +4,7 @@ > # It produces gPeiUsb2HostControllerPpiGuid based on > gPeiUsbControllerPpiGuid > # which is used to enable recovery function from USB Drivers. > # > -# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
> +# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
> # > # This program and the accompanying materials > # are licensed and made available under the terms and conditions > @@ -43,6 +43,7 @@ [Sources] > EhciSched.h > EhciUrb.h > UsbHcMem.h > + DmaMem.c >=20 >=20 > [Packages] > @@ -61,7 +62,8 @@ [LibraryClasses] > [Ppis] > gPeiUsb2HostControllerPpiGuid ## PRODUCES > gPeiUsbControllerPpiGuid ## CONSUMES > - > + gEdkiiIoMmuPpiGuid ## CONSUMES > + gEfiEndOfPeiSignalPpiGuid ## CONSUMES >=20 > [Depex] > gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND > gEfiPeiBootInRecoveryModePpiGuid > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c > b/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c > index e992d4f28797..606a53db1da1 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c > +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c > @@ -2,7 +2,7 @@ > PEIM to produce gPeiUsb2HostControllerPpiGuid based on > gPeiUsbControllerPpiGuid > which is used to enable recovery function from USB Drivers. >=20 > -Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -107,11 +107,13 @@ EhcInitSched ( > IN PEI_USB2_HC_DEV *Ehc > ) > { > + VOID *Buf; > EFI_PHYSICAL_ADDRESS PhyAddr; > VOID *Map; > UINTN Index; > UINT32 *Desc; > EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS PciAddr; >=20 > // > // First initialize the periodical schedule data: > @@ -124,15 +126,19 @@ EhcInitSched ( > // The Frame List ocupies 4K bytes, > // and must be aligned on 4-Kbyte boundaries. > // > - Status =3D PeiServicesAllocatePages ( > - EfiBootServicesCode, > + Status =3D IoMmuAllocateBuffer ( > + Ehc->IoMmu, > 1, > - &PhyAddr > + &Buf, > + &PhyAddr, > + &Map > ); >=20 > - Map =3D NULL; > - Ehc->PeriodFrameHost =3D (VOID *)(UINTN)PhyAddr; > - Ehc->PeriodFrame =3D (VOID *)(UINTN)PhyAddr; > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Ehc->PeriodFrame =3D Buf; > Ehc->PeriodFrameMap =3D Map; > Ehc->High32bitAddr =3D EHC_HIGH_32BIT (PhyAddr); >=20 > @@ -161,19 +167,20 @@ EhcInitSched ( > // Initialize the frame list entries then set the registers > // > Desc =3D (UINT32 *) Ehc->PeriodFrame; > - > + PciAddr =3D UsbHcGetPciAddressForHostMem (Ehc->MemPool, > Ehc->PeriodOne, sizeof (PEI_EHC_QH)); > for (Index =3D 0; Index < EHC_FRAME_LEN; Index++) { > - Desc[Index] =3D QH_LINK (Ehc->PeriodOne, EHC_TYPE_QH, FALSE); > + Desc[Index] =3D QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); > } >=20 > - EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT > (Ehc->PeriodFrame)); > + EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT > (PhyAddr)); >=20 > // > // Second initialize the asynchronous schedule: > // Only need to set the AsynListAddr register to > // the reclamation header > // > - EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT > (Ehc->ReclaimHead)); > + PciAddr =3D UsbHcGetPciAddressForHostMem (Ehc->MemPool, > Ehc->ReclaimHead, sizeof (PEI_EHC_QH)); > + EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT > (PciAddr)); > return EFI_SUCCESS; > } >=20 > @@ -192,26 +199,27 @@ EhcFreeSched ( > EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, 0); >=20 > if (Ehc->PeriodOne !=3D NULL) { > - UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH)); > + UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->PeriodOne, sizeof > (PEI_EHC_QH)); > Ehc->PeriodOne =3D NULL; > } >=20 > if (Ehc->ReclaimHead !=3D NULL) { > - UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof > (PEI_EHC_QH)); > + UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ReclaimHead, sizeof > (PEI_EHC_QH)); > Ehc->ReclaimHead =3D NULL; > } >=20 > if (Ehc->ShortReadStop !=3D NULL) { > - UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof > (PEI_EHC_QTD)); > + UsbHcFreeMem (Ehc, Ehc->MemPool, Ehc->ShortReadStop, sizeof > (PEI_EHC_QTD)); > Ehc->ShortReadStop =3D NULL; > } >=20 > if (Ehc->MemPool !=3D NULL) { > - UsbHcFreeMemPool (Ehc->MemPool); > + UsbHcFreeMemPool (Ehc, Ehc->MemPool); > Ehc->MemPool =3D NULL; > } >=20 > if (Ehc->PeriodFrame !=3D NULL) { > + IoMmuFreeBuffer (Ehc->IoMmu, 1, Ehc->PeriodFrame, > Ehc->PeriodFrameMap); > Ehc->PeriodFrame =3D NULL; > } > } > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c > b/MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c > index 597a4947f5bc..3dadcd60b6fe 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c > +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhciUrb.c > @@ -2,7 +2,7 @@ > PEIM to produce gPeiUsb2HostControllerPpiGuid based on > gPeiUsbControllerPpiGuid > which is used to enable recovery function from USB Drivers. >=20 > -Copyright (c) 2010, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -301,7 +301,7 @@ EhcFreeQtds ( > Qtd =3D EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList); >=20 > RemoveEntryList (&Qtd->QtdList); > - UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD)); > + UsbHcFreeMem (Ehc, Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD)); > } > } >=20 > @@ -318,13 +318,21 @@ EhcFreeUrb ( > IN PEI_URB *Urb > ) > { > + if (Urb->RequestPhy !=3D NULL) { > + IoMmuUnmap (Ehc->IoMmu, Urb->RequestMap); > + } > + > + if (Urb->DataMap !=3D NULL) { > + IoMmuUnmap (Ehc->IoMmu, Urb->DataMap); > + } > + > if (Urb->Qh !=3D NULL) { > // > // Ensure that this queue head has been unlinked from the > // schedule data structures. Free all the associated QTDs > // > EhcFreeQtds (Ehc, &Urb->Qh->Qtds); > - UsbHcFreeMem (Ehc->MemPool, Urb->Qh, sizeof (PEI_EHC_QH)); > + UsbHcFreeMem (Ehc, Ehc->MemPool, Urb->Qh, sizeof (PEI_EHC_QH)); > } > } >=20 > @@ -527,13 +535,11 @@ EhcCreateUrb ( > { > USB_ENDPOINT *Ep; > EFI_PHYSICAL_ADDRESS PhyAddr; > + EDKII_IOMMU_OPERATION MapOp; > EFI_STATUS Status; > UINTN Len; > PEI_URB *Urb; > VOID *Map; > - > - > - Map =3D NULL; >=20 > Urb =3D Ehc->Urb; > Urb->Signature =3D EHC_URB_SIG; > @@ -576,24 +582,40 @@ EhcCreateUrb ( > // > if (Request !=3D NULL) { > Len =3D sizeof (EFI_USB_DEVICE_REQUEST); > - PhyAddr =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Request ; > - if ( (Len !=3D sizeof (EFI_USB_DEVICE_REQUEST))) { > + MapOp =3D EdkiiIoMmuOperationBusMasterRead; > + Status =3D IoMmuMap (Ehc->IoMmu, MapOp, Request, &Len, &PhyAddr, > &Map); > + > + if (EFI_ERROR (Status) || (Len !=3D sizeof (EFI_USB_DEVICE_REQUEST))= ) { > goto ON_ERROR; > } >=20 > Urb->RequestPhy =3D (VOID *) ((UINTN) PhyAddr); > Urb->RequestMap =3D Map; > + } else { > + Urb->RequestPhy =3D NULL; > + Urb->RequestMap =3D NULL; > } >=20 > if (Data !=3D NULL) { > Len =3D DataLen; > - PhyAddr =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Data ; > - if ( (Len !=3D DataLen)) { > + > + if (Ep->Direction =3D=3D EfiUsbDataIn) { > + MapOp =3D EdkiiIoMmuOperationBusMasterWrite; > + } else { > + MapOp =3D EdkiiIoMmuOperationBusMasterRead; > + } > + > + Status =3D IoMmuMap (Ehc->IoMmu, MapOp, Data, &Len, &PhyAddr, > &Map); > + > + if (EFI_ERROR (Status) || (Len !=3D DataLen)) { > goto ON_ERROR; > } >=20 > Urb->DataPhy =3D (VOID *) ((UINTN) PhyAddr); > Urb->DataMap =3D Map; > + } else { > + Urb->DataPhy =3D NULL; > + Urb->DataMap =3D NULL; > } >=20 > Status =3D EhcCreateQtds (Ehc, Urb); > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c > b/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c > index 5f9f5f0718f3..a0419bd85722 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c > +++ b/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c > @@ -2,7 +2,7 @@ > PEIM to produce gPeiUsb2HostControllerPpiGuid based on > gPeiUsbControllerPpiGuid > which is used to enable recovery function from USB Drivers. >=20 > -Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -79,16 +79,18 @@ UsbHcAllocMemBlock ( >=20 > Block->Bits =3D (UINT8 *)(UINTN)TempPtr; >=20 > - > - Status =3D PeiServicesAllocatePages ( > - EfiBootServicesCode, > + Status =3D IoMmuAllocateBuffer ( > + Ehc->IoMmu, > Pages, > - &TempPtr > + (VOID **) &BufHost, > + &MappedAddr, > + &Mapping > ); > - ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + ZeroMem (BufHost, Pages*EFI_PAGE_SIZE); >=20 > - BufHost =3D (VOID *)(UINTN)TempPtr; > - MappedAddr =3D (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost; > // > // Check whether the data structure used by the host controller > // should be restricted into the same 4G > @@ -109,17 +111,21 @@ UsbHcAllocMemBlock ( > /** > Free the memory block from the memory pool. >=20 > + @param Ehc The EHCI device. > @param Pool The memory pool to free the block from. > @param Block The memory block to free. >=20 > **/ > VOID > UsbHcFreeMemBlock ( > + IN PEI_USB2_HC_DEV *Ehc, > IN USBHC_MEM_POOL *Pool, > IN USBHC_MEM_BLOCK *Block > ) > { > ASSERT ((Pool !=3D NULL) && (Block !=3D NULL)); > + > + IoMmuFreeBuffer (Ehc->IoMmu, EFI_SIZE_TO_PAGES (Block->BufLen), > Block->BufHost, Block->Mapping); > } >=20 > /** > @@ -196,6 +202,54 @@ UsbHcAllocMemFromBlock ( > } >=20 > /** > + Calculate the corresponding pci bus address according to the Mem param= eter. > + > + @param Pool The memory pool of the host controller. > + @param Mem The pointer to host memory. > + @param Size The size of the memory region. > + > + @return the pci memory address > +**/ > +EFI_PHYSICAL_ADDRESS > +UsbHcGetPciAddressForHostMem ( > + IN USBHC_MEM_POOL *Pool, > + IN VOID *Mem, > + IN UINTN Size > + ) > +{ > + USBHC_MEM_BLOCK *Head; > + USBHC_MEM_BLOCK *Block; > + UINTN AllocSize; > + EFI_PHYSICAL_ADDRESS PhyAddr; > + UINTN Offset; > + > + Head =3D Pool->Head; > + AllocSize =3D USBHC_MEM_ROUND (Size); > + > + if (Mem =3D=3D NULL) { > + return 0; > + } > + > + for (Block =3D Head; Block !=3D NULL; Block =3D Block->Next) { > + // > + // scan the memory block list for the memory block that > + // completely contains the allocated memory. > + // > + if ((Block->BufHost <=3D (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSi= ze) <=3D > (Block->BufHost + Block->BufLen))) { > + break; > + } > + } > + > + ASSERT ((Block !=3D NULL)); > + // > + // calculate the pci memory address for host memory address. > + // > + Offset =3D (UINT8 *)Mem - Block->BufHost; > + PhyAddr =3D (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset); > + return PhyAddr; > +} > + > +/** > Insert the memory block to the pool's list of the blocks. >=20 > @param Head The head of the memory pool's block list. > @@ -316,7 +370,8 @@ UsbHcInitMemPool ( >=20 > /** > Release the memory management pool. > - > + > + @param Ehc The EHCI device. > @param Pool The USB memory pool to free. >=20 > @retval EFI_DEVICE_ERROR Fail to free the memory pool. > @@ -325,6 +380,7 @@ UsbHcInitMemPool ( > **/ > EFI_STATUS > UsbHcFreeMemPool ( > + IN PEI_USB2_HC_DEV *Ehc, > IN USBHC_MEM_POOL *Pool > ) > { > @@ -337,11 +393,11 @@ UsbHcFreeMemPool ( > // UsbHcUnlinkMemBlock can't be used to unlink and free the > // first block. > // > - for (Block =3D Pool->Head->Next; Block !=3D NULL; Block =3D Pool->Head= ->Next) { > - UsbHcFreeMemBlock (Pool, Block); > + for (Block =3D Pool->Head->Next; Block !=3D NULL; Block =3D Block->Nex= t) { > + UsbHcFreeMemBlock (Ehc, Pool, Block); > } >=20 > - UsbHcFreeMemBlock (Pool, Pool->Head); > + UsbHcFreeMemBlock (Ehc, Pool, Pool->Head); >=20 > return EFI_SUCCESS; > } > @@ -425,6 +481,7 @@ UsbHcAllocateMem ( > /** > Free the allocated memory back to the memory pool. >=20 > + @param Ehc The EHCI device. > @param Pool The memory pool of the host controller. > @param Mem The memory to free. > @param Size The size of the memory to free. > @@ -432,6 +489,7 @@ UsbHcAllocateMem ( > **/ > VOID > UsbHcFreeMem ( > + IN PEI_USB2_HC_DEV *Ehc, > IN USBHC_MEM_POOL *Pool, > IN VOID *Mem, > IN UINTN Size > @@ -486,7 +544,7 @@ UsbHcFreeMem ( > // Release the current memory block if it is empty and not the head > // > if ((Block !=3D Head) && UsbHcIsMemBlockEmpty (Block)) { > - UsbHcFreeMemBlock (Pool, Block); > + UsbHcFreeMemBlock (Ehc, Pool, Block); > } >=20 > return ; > diff --git a/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h > b/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h > index 586d12af9658..717a8c822c90 100644 > --- a/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h > +++ b/MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.h > @@ -1,7 +1,7 @@ > /** @file > Private Header file for Usb Host Controller PEIM >=20 > -Copyright (c) 2010, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
>=20 > This program and the accompanying materials > are licensed and made available under the terms and conditions > @@ -74,4 +74,20 @@ typedef struct _USBHC_MEM_POOL { > } while (0) >=20 >=20 > +/** > + Calculate the corresponding pci bus address according to the Mem param= eter. > + > + @param Pool The memory pool of the host controller. > + @param Mem The pointer to host memory. > + @param Size The size of the memory region. > + > + @return the pci memory address > +**/ > +EFI_PHYSICAL_ADDRESS > +UsbHcGetPciAddressForHostMem ( > + IN USBHC_MEM_POOL *Pool, > + IN VOID *Mem, > + IN UINTN Size > + ); > + > #endif > -- > 2.7.0.windows.1