From nobody Fri May 3 05:29:32 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1510818461297679.0508337432682; Wed, 15 Nov 2017 23:47:41 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id CDC0320355206; Wed, 15 Nov 2017 23:43:29 -0800 (PST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (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 56B99220D4BFE for ; Wed, 15 Nov 2017 23:43:29 -0800 (PST) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Nov 2017 23:47:37 -0800 Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.9.31]) by fmsmga005.fm.intel.com with ESMTP; 15 Nov 2017 23:47:36 -0800 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.24; helo=mga09.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,402,1505804400"; d="scan'208";a="176369748" From: Star Zeng To: edk2-devel@lists.01.org Date: Thu, 16 Nov 2017 15:47:34 +0800 Message-Id: <1510818454-54360-1-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 Subject: [edk2] [PATCH] 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: , Cc: Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Update the EhciPei driver to consume IOMMU_PPI to allocate DMA buffer. If no IOMMU_PPI exists, this driver still calls PEI service to allocate DMA buffer, with assumption that DRAM=3D=3DDMA. 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 | 4 +- MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h | 110 +++++++++++++- MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf | 5 +- 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, 506 insertions(+), 45 deletions(-) create mode 100644 MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c diff --git a/MdeModulePkg/Bus/Pci/EhciPei/DmaMem.c b/MdeModulePkg/Bus/Pci/E= hciPei/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 IMPLI= ED. + +**/ + +#include "EhcPeim.h" + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param IoMmu Pointer to IOMMU PPI. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_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 OperationBusMasterCommonBuffer = 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 mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN 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 allocate= d 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..45fe71802cc4 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 gPeiUsbControllerPp= iGuid 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 @@ -1219,6 +1219,8 @@ EhcPeimEntry ( =20 EhcDev->Signature =3D USB2_HC_DEV_SIGNATURE; =20 + IoMmuInit (&EhcDev->IoMmu); + EhcDev->UsbHostControllerBaseAddress =3D (UINT32) BaseAddress; =20 =20 diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.h b/MdeModulePkg/Bus/Pci/= EhciPei/EhcPeim.h index d7a68d909547..791a18e6f2ee 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,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. =20 #include #include +#include =20 #include #include @@ -94,6 +95,7 @@ typedef struct _PEI_USB2_HC_DEV PEI_USB2_HC_DEV; struct _PEI_USB2_HC_DEV { UINTN Signature; PEI_USB2_HOST_CONTROLLER_PPI Usb2HostControllerPpi; + EDKII_IOMMU_PPI *IoMmu; EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; =20 UINT32 UsbHostControllerBaseAddress; PEI_URB *Urb; @@ -122,7 +124,6 @@ struct _PEI_USB2_HC_DEV { // Periodic (interrupt) transfer schedule data: // VOID *PeriodFrame; // Mapped as commo= n buffer=20 - VOID *PeriodFrameHost; VOID *PeriodFrameMap; =20 PEI_EHC_QH *PeriodOne; @@ -173,7 +174,8 @@ UsbHcInitMemPool ( =20 /** Release the memory management pool. - =20 + + @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 +184,7 @@ UsbHcInitMemPool ( **/ EFI_STATUS UsbHcFreeMemPool ( + IN PEI_USB2_HC_DEV *Ehc, IN USBHC_MEM_POOL *Pool ) ; @@ -208,6 +211,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 +219,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 mem= ory from a + DMA bus master. + + @param IoMmu Pointer to IOMMU PPI. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_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 OperationBusMasterCommonBuffer = 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 mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN 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 allocate= d 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/Pc= i/EhciPei/EhciPei.inf index 7083f8668150..0c40187f9eb6 100644 --- a/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf +++ b/MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf @@ -4,7 +4,7 @@ # It produces gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiG= uid # 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,7 @@ [LibraryClasses] [Ppis] gPeiUsb2HostControllerPpiGuid ## PRODUCES gPeiUsbControllerPpiGuid ## CONSUMES - + gEdkiiIoMmuPpiGuid ## CONSUMES =20 [Depex] gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiB= ootInRecoveryModePpiGuid diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c b/MdeModulePkg/Bus/Pc= i/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 gPeiUsbControllerPp= iGuid 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->PeriodFra= me)); + 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->ReclaimHe= ad)); + PciAddr =3D UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHea= d, 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_Q= TD)); 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 gPeiUsbControllerPp= iGuid 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; - - =20 - 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 gPeiUsbControllerPp= iGuid 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 - =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->B= ufHost, Block->Mapping); } =20 /** @@ -196,6 +202,54 @@ UsbHcAllocMemFromBlock ( } =20 /** + Calculate the corresponding pci bus address according to the Mem paramet= er. + + @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 + AllocSize= ) <=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. - =20 + + @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->Next)= { + 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 =20 +/** + Calculate the corresponding pci bus address according to the Mem paramet= er. + + @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 --=20 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel