From nobody Thu Dec 26 13:48:33 2024 Delivered-To: importer@patchew.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; 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 1504883083001693.7293483608747; Fri, 8 Sep 2017 08:04:43 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6431821E2BE37; Fri, 8 Sep 2017 08:01:21 -0700 (PDT) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (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 7E5F620945BFC for ; Fri, 8 Sep 2017 08:01:19 -0700 (PDT) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 Sep 2017 08:04:11 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.209.82]) by fmsmga004.fm.intel.com with ESMTP; 08 Sep 2017 08:04:10 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.42,361,1500966000"; d="scan'208";a="309511694" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Fri, 8 Sep 2017 23:03:54 +0800 Message-Id: <1504883034-22060-12-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1504883034-22060-1-git-send-email-jiewen.yao@intel.com> References: <1504883034-22060-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [PATCH 11/11] MdeModulePkg/XhciPei: 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: 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 XHCI 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. This is a compatible change. Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao --- MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c | 249 ++++++++++++++++++++ MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c | 55 +++-- MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h | 9 +- MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c | 55 ++++- MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h | 107 +++++++++ MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf | 3 + MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c | 47 +++- MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h | 1 + 8 files changed, 492 insertions(+), 34 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c b/MdeModulePkg/Bus/Pci/X= hciPei/DmaMem.c new file mode 100644 index 0000000..6e2c1b5 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c @@ -0,0 +1,249 @@ +/** @file +The DMA memory help function. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "XhcPeim.h" + +EDKII_IOMMU_PPI *mIoMmu; + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @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_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->Map ( + mIoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute =3D EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute =3D EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + *Mapping =3D NULL; + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system 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 UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + + *HostAddress =3D NULL; + *DeviceAddress =3D 0; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->AllocateBuffer ( + mIoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes =3D EFI_PAGES_TO_SIZE(Pages); + Status =3D mIoMmu->Map ( + mIoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status =3D PeiServicesAllocatePages ( + EfiBootServicesData, + Pages, + &HostPhyAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + *HostAddress =3D (VOID *)(UINTN)HostPhyAddress; + *DeviceAddress =3D HostPhyAddress; + *Mapping =3D NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress = and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + Status =3D mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ) +{ + PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **)&mIoMmu + ); +} + diff --git a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c b/MdeModulePkg/Bus/Pci= /XhciPei/UsbHcMem.c index 6a3f3a5..5d0232c 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c +++ b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c @@ -31,6 +31,9 @@ UsbHcAllocMemBlock ( ) { USBHC_MEM_BLOCK *Block; + VOID *BufHost; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS MappedAddr; EFI_STATUS Status; UINTN PageNumber; EFI_PHYSICAL_ADDRESS TempPtr; @@ -71,18 +74,20 @@ UsbHcAllocMemBlock ( =20 Block->Bits =3D (UINT8 *) (UINTN) TempPtr; =20 - Status =3D PeiServicesAllocatePages ( - EfiBootServicesData, + Status =3D IoMmuAllocateBuffer ( Pages, - &TempPtr + &BufHost, + &MappedAddr, + &Mapping ); if (EFI_ERROR (Status)) { return NULL; } - ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (Pages)); + ZeroMem ((VOID *) (UINTN) BufHost, EFI_PAGES_TO_SIZE (Pages)); =20 - Block->BufHost =3D (UINT8 *) (UINTN) TempPtr;; - Block->Buf =3D (UINT8 *) (UINTN) TempPtr; + Block->BufHost =3D (UINT8 *) (UINTN) BufHost; + Block->Buf =3D (UINT8 *) (UINTN) MappedAddr; + Block->Mapping =3D Mapping; Block->Next =3D NULL; =20 return Block; @@ -102,6 +107,9 @@ UsbHcFreeMemBlock ( ) { ASSERT ((Pool !=3D NULL) && (Block !=3D NULL)); + + IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Bloc= k->Mapping); + // // No free memory in PEI. // @@ -567,6 +575,7 @@ UsbHcFreeMem ( @param HostAddress The system memory address to map to the PC= I controller. @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(). =20 @retval EFI_SUCCESS Success to allocate aligned pages. @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid. @@ -578,13 +587,16 @@ UsbHcAllocateAlignedPages ( IN UINTN Pages, IN UINTN Alignment, OUT VOID **HostAddress, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping ) { EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS Memory; + VOID *Memory; UINTN AlignedMemory; UINTN AlignmentMask; + EFI_PHYSICAL_ADDRESS DeviceMemory; + UINTN AlignedDeviceMemory; UINTN RealPages; =20 // @@ -611,32 +623,36 @@ UsbHcAllocateAlignedPages ( // ASSERT (RealPages > Pages); =20 - Status =3D PeiServicesAllocatePages ( - EfiBootServicesData, + Status =3D IoMmuAllocateBuffer ( Pages, - &Memory + &Memory, + &DeviceMemory, + Mapping ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } AlignedMemory =3D ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + AlignedDeviceMemory =3D ((UINTN) DeviceMemory + AlignmentMask) & ~Alig= nmentMask; } else { // // Do not over-allocate pages in this case. // - Status =3D PeiServicesAllocatePages ( - EfiBootServicesData, + Status =3D IoMmuAllocateBuffer ( Pages, - &Memory + &Memory, + &DeviceMemory, + Mapping ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } AlignedMemory =3D (UINTN) Memory; + AlignedDeviceMemory =3D (UINTN) DeviceMemory; } =20 *HostAddress =3D (VOID *) AlignedMemory; - *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS) AlignedMemory; + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS) AlignedDeviceMemory; =20 return EFI_SUCCESS; } @@ -646,17 +662,18 @@ UsbHcAllocateAlignedPages ( =20 @param HostAddress The system memory address to map to the PC= I controller. @param Pages The number of pages to free. + @param Mapping The mapping value returned from Map(). =20 **/ VOID UsbHcFreeAlignedPages ( IN VOID *HostAddress, - IN UINTN Pages + IN UINTN Pages, + IN VOID *Mapping ) { ASSERT (Pages !=3D 0); - // - // No free memory in PEI. - // + + IoMmuFreeBuffer (Pages, HostAddress, Mapping); } =20 diff --git a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h b/MdeModulePkg/Bus/Pci= /XhciPei/UsbHcMem.h index c314e92..c315e6e 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h +++ b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h @@ -29,6 +29,7 @@ struct _USBHC_MEM_BLOCK { UINT8 *Buf; UINT8 *BufHost; UINTN BufLen; // Memory size in bytes + VOID *Mapping; USBHC_MEM_BLOCK *Next; }; =20 @@ -112,6 +113,7 @@ UsbHcGetHostAddrForPciAddr ( @param HostAddress The system memory address to map to the PC= I controller. @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(). =20 @retval EFI_SUCCESS Success to allocate aligned pages. @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid. @@ -123,7 +125,8 @@ UsbHcAllocateAlignedPages ( IN UINTN Pages, IN UINTN Alignment, OUT VOID **HostAddress, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping ); =20 /** @@ -131,12 +134,14 @@ UsbHcAllocateAlignedPages ( =20 @param HostAddress The system memory address to map to the PC= I controller. @param Pages The number of pages to free. + @param Mapping The mapping value returned from Map(). =20 **/ VOID UsbHcFreeAlignedPages ( IN VOID *HostAddress, - IN UINTN Pages + IN UINTN Pages, + IN VOID *Mapping ); =20 #endif diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c b/MdeModulePkg/Bus/Pci/= XhciPei/XhcPeim.c index 38f0d21..99f69f7 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c @@ -662,7 +662,8 @@ XhcPeiControlTransfer ( if (EFI_ERROR(RecoveryStatus)) { DEBUG((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndp= oint failed\n")); } - goto FREE_URB; + XhcPeiFreeUrb (Xhc, Urb); + goto ON_EXIT; } else { if (*TransferResult =3D=3D EFI_USB_NOERROR) { Status =3D EFI_SUCCESS; @@ -672,11 +673,17 @@ XhcPeiControlTransfer ( DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEn= dpoint failed\n")); } Status =3D EFI_DEVICE_ERROR; - goto FREE_URB; + XhcPeiFreeUrb (Xhc, Urb); + goto ON_EXIT; } else { - goto FREE_URB; + XhcPeiFreeUrb (Xhc, Urb); + goto ON_EXIT; } } + // + // Unmap data before consume. + // + XhcPeiFreeUrb (Xhc, Urb); =20 // // Hook Get_Descriptor request from UsbBus as we need evaluate context a= nd configure endpoint. @@ -704,7 +711,7 @@ XhcPeiControlTransfer ( Xhc->UsbDevContext[SlotId].ConfDesc =3D AllocateZeroPool (Xhc->UsbDe= vContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIP= TOR *)); if (Xhc->UsbDevContext[SlotId].ConfDesc =3D=3D NULL) { Status =3D EFI_OUT_OF_RESOURCES; - goto FREE_URB; + goto ON_EXIT; } if (Xhc->HcCParams.Data.Csz =3D=3D 0) { Status =3D XhcPeiEvaluateContext (Xhc, SlotId, MaxPacket0); @@ -722,7 +729,7 @@ XhcPeiControlTransfer ( Xhc->UsbDevContext[SlotId].ConfDesc[Index] =3D AllocateZeroPool (*= DataLength); if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] =3D=3D NULL) { Status =3D EFI_OUT_OF_RESOURCES; - goto FREE_URB; + goto ON_EXIT; } CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLe= ngth); } @@ -844,9 +851,6 @@ XhcPeiControlTransfer ( *(UINT32 *) Data =3D *(UINT32 *) &PortStatus; } =20 -FREE_URB: - XhcPeiFreeUrb (Xhc, Urb); - ON_EXIT: =20 if (EFI_ERROR (Status)) { @@ -1399,6 +1403,34 @@ XhcPeiGetRootHubPortStatus ( } =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 Notific= ation event that + caused this function to execute. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + @retval others +**/ +EFI_STATUS +EFIAPI +XhcEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + PEI_XHC_DEV *Xhc; + + Xhc =3D PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(NotifyDescriptor); + + XhcPeiHaltHC (Xhc, XHC_GENERIC_TIMEOUT); + + return EFI_SUCCESS; +} + +/** @param FileHandle Handle of the file being invoked. @param PeiServices Describes the list of possible PEI Services. =20 @@ -1429,6 +1461,8 @@ XhcPeimEntry ( return EFI_SUCCESS; } =20 + IoMmuInit (); + Status =3D PeiServicesLocatePpi ( &gPeiUsbControllerPpiGuid, 0, @@ -1530,7 +1564,12 @@ XhcPeimEntry ( XhcDev->PpiDescriptor.Guid =3D &gPeiUsb2HostControllerPpiGuid; XhcDev->PpiDescriptor.Ppi =3D &XhcDev->Usb2HostControllerPpi; =20 + XhcDev->EndOfPeiNotifyList.Flags =3D (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CA= LLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + XhcDev->EndOfPeiNotifyList.Guid =3D &gEfiEndOfPeiSignalPpiGuid; + XhcDev->EndOfPeiNotifyList.Notify =3D XhcEndOfPei; + PeiServicesInstallPpi (&XhcDev->PpiDescriptor); + PeiServicesNotifyPpi (&XhcDev->EndOfPeiNotifyList); =20 Index++; } diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h b/MdeModulePkg/Bus/Pci/= XhciPei/XhcPeim.h index 99f0396..e7a100f 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h @@ -21,6 +21,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. =20 #include #include +#include +#include =20 #include #include @@ -153,6 +155,12 @@ struct _PEI_XHC_DEV { USBHC_MEM_POOL *MemPool; =20 // + // EndOfPei callback is used to stop the XHC DMA operation + // after exit PEI phase. + // + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; + + // // XHCI configuration data // UINT8 CapLength; ///< Capability Register= Length @@ -164,7 +172,9 @@ struct _PEI_XHC_DEV { UINT32 PageSize; UINT32 MaxScratchpadBufs; UINT64 *ScratchBuf; + VOID *ScratchMap; UINT64 *ScratchEntry; + UINTN *ScratchEntryMap; UINT64 *DCBAA; UINT32 MaxSlotsEn; // @@ -184,6 +194,7 @@ struct _PEI_XHC_DEV { }; =20 #define PEI_RECOVERY_USB_XHC_DEV_FROM_THIS(a) CR (a, PEI_XHC_DEV, Usb2Host= ControllerPpi, USB_XHC_DEV_SIGNATURE) +#define PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(a) CR (a, PEI_XHC_DEV, E= ndOfPeiNotifyList, USB_XHC_DEV_SIGNATURE) =20 /** Initialize the memory management pool for the host controller. @@ -242,4 +253,100 @@ UsbHcFreeMem ( ) ; =20 + +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ); + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @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_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 b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem 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 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 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 allo= cated 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 + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf b/MdeModulePkg/Bus/Pc= i/XhciPei/XhciPei.inf index dc65f28..f307ea7 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf @@ -37,6 +37,7 @@ XhcPeim.h XhciSched.c UsbHcMem.c + DmaMem.c XhciReg.h XhciSched.h UsbHcMem.h @@ -56,6 +57,8 @@ [Ppis] gPeiUsb2HostControllerPpiGuid ## PRODUCES gPeiUsbControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 [Depex] gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiB= ootInRecoveryModePpiGuid diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c b/MdeModulePkg/Bus/Pc= i/XhciPei/XhciSched.c index 3dd2b89..e5aee49 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c @@ -200,6 +200,8 @@ XhcPeiFreeUrb ( return; } =20 + IoMmuUnmap (Urb->DataMap); + FreePool (Urb); } =20 @@ -227,6 +229,10 @@ XhcPeiCreateTransferTrb ( UINTN TotalLen; UINTN Len; UINTN TrbNum; + EDKII_IOMMU_OPERATION MapOp; + EFI_PHYSICAL_ADDRESS PhyAddr; + VOID *Map; + EFI_STATUS Status; =20 SlotId =3D XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr); if (SlotId =3D=3D 0) { @@ -249,7 +255,27 @@ XhcPeiCreateTransferTrb ( EPType =3D (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EP= Type; } =20 - Urb->DataPhy =3D Urb->Data; + // + // No need to remap. + // + if ((Urb->Data !=3D NULL) && (Urb->DataMap =3D=3D NULL)) { + if (((UINT8) (Urb->Ep.Direction)) =3D=3D EfiUsbDataIn) { + MapOp =3D EdkiiIoMmuOperationBusMasterWrite; + } else { + MapOp =3D EdkiiIoMmuOperationBusMasterRead; + } + + Len =3D Urb->DataLen; + Status =3D IoMmuMap (MapOp, Urb->Data, &Len, &PhyAddr, &Map); + + if (EFI_ERROR (Status) || (Len !=3D Urb->DataLen)) { + DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n= ")); + return EFI_OUT_OF_RESOURCES; + } + + Urb->DataPhy =3D (VOID *) ((UINTN) PhyAddr); + Urb->DataMap =3D Map; + } =20 // // Construct the TRB @@ -2812,6 +2838,7 @@ XhcPeiInitSched ( UINT64 *ScratchEntry; EFI_PHYSICAL_ADDRESS ScratchEntryPhy; UINT32 Index; + UINTN *ScratchEntryMap; EFI_STATUS Status; =20 // @@ -2848,6 +2875,13 @@ XhcPeiInitSched ( ASSERT (MaxScratchpadBufs <=3D 1023); if (MaxScratchpadBufs !=3D 0) { // + // Allocate the buffer to record the Mapping for each scratch buffer i= n order to Unmap them + // + ScratchEntryMap =3D AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBu= fs); + ASSERT (ScratchEntryMap !=3D NULL); + Xhc->ScratchEntryMap =3D ScratchEntryMap; + + // // Allocate the buffer to record the host address for each entry // ScratchEntry =3D AllocateZeroPool (sizeof (UINT64) * MaxScratchpadBufs= ); @@ -2859,7 +2893,8 @@ XhcPeiInitSched ( EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)), Xhc->PageSize, (VOID **) &ScratchBuf, - &ScratchPhy + &ScratchPhy, + &Xhc->ScratchMap ); ASSERT_EFI_ERROR (Status); =20 @@ -2875,7 +2910,8 @@ XhcPeiInitSched ( EFI_SIZE_TO_PAGES (Xhc->PageSize), Xhc->PageSize, (VOID **) &ScratchEntry[Index], - &ScratchEntryPhy + &ScratchEntryPhy, + (VOID **) &ScratchEntryMap[Index] ); ASSERT_EFI_ERROR (Status); ZeroMem ((VOID *) (UINTN) ScratchEntry[Index], Xhc->PageSize); @@ -2967,12 +3003,13 @@ XhcPeiFreeSched ( // // Free Scratchpad Buffers // - UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE= _TO_PAGES (Xhc->PageSize)); + UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE= _TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]); } // // Free Scratchpad Buffer Array // - UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScr= atchpadBufs * sizeof (UINT64))); + UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScr= atchpadBufs * sizeof (UINT64)), Xhc->ScratchMap); + FreePool (Xhc->ScratchEntryMap); FreePool (Xhc->ScratchEntry); } =20 diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h b/MdeModulePkg/Bus/Pc= i/XhciPei/XhciSched.h index b3d4c45..faf2e63 100644 --- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h +++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h @@ -170,6 +170,7 @@ typedef struct _URB { VOID *Data; UINTN DataLen; VOID *DataPhy; + VOID *DataMap; EFI_ASYNC_USB_TRANSFER_CALLBACK Callback; VOID *Context; // --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel