* [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support
@ 2016-12-09 15:04 Ard Biesheuvel
2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
0 siblings, 2 replies; 6+ messages in thread
From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel
These are the two patches that remain from the series 'MdeModulePkg: add
support for non-discoverable devices', whose v5 I have partially merged.
What remains is:
- a patch that enhances NonDiscoverablePciDeviceDxe to support non-coherent
DMA masters, which are not uncommon on ARM platforms
- a patch that replaces the existing BeagleBoard PciEmulation code with a
slim driver that builds on top of NonDiscoverablePciDeviceDxe to drive
the non-coherent non-PCI EHCI controller on the OMAP 3630.
Changes since v5:
- add missing EFIAPI modifiers to non-coherent PCI I/O protocol methods
Ard Biesheuvel (2):
MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
DMA
Omap35xxPkg/PciEmulation: port to new non-discoverable device
infrastructure
BeagleBoardPkg/BeagleBoardPkg.dsc | 2 +
BeagleBoardPkg/BeagleBoardPkg.fdf | 1 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +-
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 +++++++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 +
Omap35xxPkg/Omap35xxPkg.dsc | 2 +-
Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +-------------------
Omap35xxPkg/PciEmulation/PciEmulation.h | 292 ----------
Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +-
Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 -----------
11 files changed, 403 insertions(+), 1168 deletions(-)
delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
--
2.7.4
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel
@ 2016-12-09 15:04 ` Ard Biesheuvel
2016-12-14 9:15 ` Ard Biesheuvel
2016-12-15 8:17 ` Ni, Ruiyu
2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
1 sibling, 2 replies; 6+ messages in thread
From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel
Add support for non-coherent DMA, either by performing explicit cache
maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment,
or by bounce buffering via uncached mappings otherwise.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Marcin Wojtas <mw@semihalf.com>
---
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +-
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 ++++++++++++++++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 ++
4 files changed, 367 insertions(+), 7 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
index ee765d7a5d9c..0fcf2b2ec1bf 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -16,6 +16,8 @@
#include <Protocol/DriverBinding.h>
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
//
// We only support the following device types
//
@@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported (
return Status;
}
- //
- // Restricted to DMA coherent for now
- //
Status = EFI_UNSUPPORTED;
- if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
- goto CloseProtocol;
- }
-
for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
Status = EFI_SUCCESS;
@@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+ ASSERT_EFI_ERROR(Status);
+
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
index 996fe310e0e3..5faa8945134c 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -32,6 +32,7 @@ [Packages]
[LibraryClasses]
BaseMemoryLib
DebugLib
+ DxeServicesTableLib
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
@@ -40,6 +41,7 @@ [LibraryClasses]
[Protocols]
gEfiPciIoProtocolGuid ## BY_START
gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
+ gEfiCpuArchProtocolGuid ## CONSUMES
[Guids]
gEdkiiNonDiscoverableAhciDeviceGuid
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index 56482e3353c0..814f7643ae4c 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -15,6 +15,8 @@
#include "NonDiscoverablePciDeviceIo.h"
+#include <Library/DxeServicesTableLib.h>
+
#include <IndustryStandard/Acpi.h>
#include <Protocol/PciRootBridgeIo.h>
@@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer (
return EFI_SUCCESS;
}
+STATIC
+EFI_STATUS
+EFIAPI
+NonCoherentPciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ LIST_ENTRY *Entry;
+ EFI_STATUS Status;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+ BOOLEAN Found;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Found = FALSE;
+
+ //
+ // Find the uncached allocation list entry associated
+ // with this allocation
+ //
+ for (Entry = Dev->UncachedAllocationList.ForwardLink;
+ Entry != &Dev->UncachedAllocationList;
+ Entry = Entry->ForwardLink) {
+
+ Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
+ if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
+ //
+ // We are freeing the exact allocation we were given
+ // before by AllocateBuffer()
+ //
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+
+ RemoveEntryList (&Alloc->List);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ Alloc->Attributes);
+ if (EFI_ERROR (Status)) {
+ goto FreeAlloc;
+ }
+
+ //
+ // If we fail to restore the original attributes, it is better to leak the
+ // memory than to return it to the heap
+ //
+ FreePages (HostAddress, Pages);
+
+FreeAlloc:
+ FreePool (Alloc);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonCoherentPciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+ EFI_STATUS Status;
+ UINT64 MemType;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+ VOID *AllocAddress;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
+ &AllocAddress, Attributes);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gDS->GetMemorySpaceDescriptor (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
+ &GcdDescriptor);
+ if (EFI_ERROR (Status)) {
+ goto FreeBuffer;
+ }
+
+ if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) {
+ Status = EFI_UNSUPPORTED;
+ goto FreeBuffer;
+ }
+
+ //
+ // Set the preferred memory attributes
+ //
+ if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
+ (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
+ //
+ // Use write combining if it was requested, or if it is the only
+ // type supported by the region.
+ //
+ MemType = EFI_MEMORY_WC;
+ } else {
+ MemType = EFI_MEMORY_UC;
+ }
+
+ Alloc = AllocatePool (sizeof *Alloc);
+ if (Alloc == NULL) {
+ goto FreeBuffer;
+ }
+
+ Alloc->HostAddress = AllocAddress;
+ Alloc->NumPages = Pages;
+ Alloc->Attributes = GcdDescriptor.Attributes;
+
+ //
+ // Record this allocation in the linked list, so we
+ // can restore the memory space attributes later
+ //
+ InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ MemType);
+ if (EFI_ERROR (Status)) {
+ goto RemoveList;
+ }
+
+ Status = mCpu->FlushDataCache (
+ mCpu,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ EfiCpuFlushTypeInvalidate);
+ if (EFI_ERROR (Status)) {
+ goto RemoveList;
+ }
+
+ *HostAddress = AllocAddress;
+
+ return EFI_SUCCESS;
+
+RemoveList:
+ RemoveEntryList (&Alloc->List);
+ FreePool (Alloc);
+
+FreeBuffer:
+ CoherentPciIoFreeBuffer (This, Pages, AllocAddress);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonCoherentPciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+ UINTN AlignMask;
+ VOID *AllocAddress;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+ BOOLEAN Bounce;
+
+ MapInfo = AllocatePool (sizeof *MapInfo);
+ if (MapInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MapInfo->HostAddress = HostAddress;
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ //
+ // If this device does not support 64-bit DMA addressing, we need to allocate
+ // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
+ //
+ Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
+ (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
+
+ if (!Bounce) {
+ switch (Operation) {
+ case EfiPciIoOperationBusMasterRead:
+ case EfiPciIoOperationBusMasterWrite:
+ //
+ // For streaming DMA, it is sufficient if the buffer is aligned to
+ // the CPUs DMA buffer alignment.
+ //
+ AlignMask = mCpu->DmaBufferAlignment - 1;
+ if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
+ break;
+ }
+ // fall through
+
+ case EfiPciIoOperationBusMasterCommonBuffer:
+ //
+ // Check whether the host address refers to an uncached mapping.
+ //
+ Status = gDS->GetMemorySpaceDescriptor (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ &GcdDescriptor);
+ if (EFI_ERROR (Status) ||
+ (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
+ Bounce = TRUE;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+ }
+
+ if (Bounce) {
+ if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+ Status = EFI_DEVICE_ERROR;
+ goto FreeMapInfo;
+ }
+
+ Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
+ EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+ &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
+ if (EFI_ERROR (Status)) {
+ goto FreeMapInfo;
+ }
+ MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
+ if (Operation == EfiPciIoOperationBusMasterRead) {
+ gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
+ }
+ *DeviceAddress = MapInfo->AllocAddress;
+ } else {
+ MapInfo->AllocAddress = 0;
+ *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+
+ //
+ // We are not using a bounce buffer: the mapping is sufficiently
+ // aligned to allow us to simply flush the caches. Note that cleaning
+ // the caches is necessary for both data directions:
+ // - for bus master read, we want the latest data to be present
+ // in main memory
+ // - for bus master write, we don't want any stale dirty cachelines that
+ // may be written back unexpectedly, and clobber the data written to
+ // main memory by the device.
+ //
+ mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ *NumberOfBytes, EfiCpuFlushTypeWriteBack);
+ }
+
+ *Mapping = MapInfo;
+ return EFI_SUCCESS;
+
+FreeMapInfo:
+ FreePool (MapInfo);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonCoherentPciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+
+ if (Mapping == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ MapInfo = Mapping;
+ if (MapInfo->AllocAddress != 0) {
+ //
+ // We are using a bounce buffer: copy back the data if necessary,
+ // and free the buffer.
+ //
+ if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+ gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,
+ MapInfo->NumberOfBytes);
+ }
+ NonCoherentPciIoFreeBuffer (This,
+ EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+ (VOID *)(UINTN)MapInfo->AllocAddress);
+ } else {
+ //
+ // We are *not* using a bounce buffer: if this is a bus master write,
+ // we have to invalidate the caches so the CPU will see the uncached
+ // data written by the device.
+ //
+ if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+ mCpu->FlushDataCache (mCpu,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
+ MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
+ }
+ }
+ FreePool (MapInfo);
+ return EFI_SUCCESS;
+}
STATIC
EFI_STATUS
@@ -726,12 +1046,21 @@ InitializePciIoProtocol (
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
INTN Idx;
+ InitializeListHead (&Dev->UncachedAllocationList);
+
Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
// Copy protocol structure
CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
+ if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
+ Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
+ Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
+ Dev->PciIo.Map = NonCoherentPciIoMap;
+ Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
+ }
+
if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {
Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
index bc0a3d3258f9..449614862911 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
@@ -15,6 +15,8 @@
#ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
+#include <PiDxe.h>
+
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -25,6 +27,7 @@
#include <Protocol/ComponentName.h>
#include <Protocol/NonDiscoverableDevice.h>
+#include <Protocol/Cpu.h>
#include <Protocol/PciIo.h>
#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D')
@@ -38,6 +41,27 @@
#define PCI_MAX_BARS 6
+extern EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+typedef struct {
+ //
+ // The linked-list next pointer
+ //
+ LIST_ENTRY List;
+ //
+ // The address of the uncached allocation
+ //
+ VOID *HostAddress;
+ //
+ // The number of pages in the allocation
+ //
+ UINTN NumPages;
+ //
+ // The attributes of the allocation
+ //
+ UINT64 Attributes;
+} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
+
typedef struct {
UINT32 Signature;
//
@@ -71,6 +95,11 @@ typedef struct {
// Whether this device has been enabled
//
BOOLEAN Enabled;
+ //
+ // Linked list to keep track of uncached allocations performed
+ // on behalf of this device
+ //
+ LIST_ENTRY UncachedAllocationList;
} NON_DISCOVERABLE_PCI_DEVICE;
VOID
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure
2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel
2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
@ 2016-12-09 15:04 ` Ard Biesheuvel
1 sibling, 0 replies; 6+ messages in thread
From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel
Move to the new non-discoverable device protocols for wiring the PCI based
EHCI controller driver to the non-discoverable EHCI controller found on the
OMAP 3530.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
BeagleBoardPkg/BeagleBoardPkg.dsc | 2 +
BeagleBoardPkg/BeagleBoardPkg.fdf | 1 +
Omap35xxPkg/Omap35xxPkg.dsc | 2 +-
Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +-------------------
Omap35xxPkg/PciEmulation/PciEmulation.h | 292 ----------
Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +-
Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 -----------
7 files changed, 36 insertions(+), 1161 deletions(-)
diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc
index 69d3c5f1841b..b24db6cbfb04 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.dsc
+++ b/BeagleBoardPkg/BeagleBoardPkg.dsc
@@ -185,6 +185,7 @@ [LibraryClasses.common.DXE_DRIVER]
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+ NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
@@ -447,6 +448,7 @@ [Components.common]
# USB
#
Omap35xxPkg/PciEmulation/PciEmulation.inf
+ MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf {
<PcdsFixedAtBuild>
diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf
index 42e097f64118..3d00355fff84 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.fdf
+++ b/BeagleBoardPkg/BeagleBoardPkg.fdf
@@ -167,6 +167,7 @@ [FV.FvMain]
#
INF Omap35xxPkg/PciEmulation/PciEmulation.inf
+ INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
diff --git a/Omap35xxPkg/Omap35xxPkg.dsc b/Omap35xxPkg/Omap35xxPkg.dsc
index 436c10bb7f2f..9395570ccaa3 100644
--- a/Omap35xxPkg/Omap35xxPkg.dsc
+++ b/Omap35xxPkg/Omap35xxPkg.dsc
@@ -80,7 +80,7 @@ [LibraryClasses.common]
[LibraryClasses.common.DXE_DRIVER]
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
-
+ NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
[LibraryClasses.ARM]
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c
index 17ea03ccf486..d17646a9ed58 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.c
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.c
@@ -1,6 +1,7 @@
/** @file
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -12,49 +13,27 @@
**/
-#include "PciEmulation.h"
+#include <PiDxe.h>
-EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
-
-#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
-typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- PCI_DEVICE_PATH PciDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
-} EFI_PCI_IO_DEVICE_PATH;
+#include <Protocol/EmbeddedExternalDevice.h>
-typedef struct {
- UINT32 Signature;
- EFI_PCI_IO_DEVICE_PATH DevicePath;
- EFI_PCI_IO_PROTOCOL PciIoProtocol;
- PCI_TYPE00 *ConfigSpace;
- PCI_ROOT_BRIDGE RootBridge;
- UINTN Segment;
-} EFI_PCI_IO_PRIVATE_DATA;
+#include <TPS65950.h>
+#include <Omap3530/Omap3530.h>
-#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
-#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
-EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
-{
- {
- { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
- EISA_PNP_ID(0x0A03), // HID
- 0 // UID
- },
- {
- { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
- 0,
- 0
- },
- { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
-};
+#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
STATIC
-VOID
+EFI_STATUS
ConfigureUSBHost (
- VOID
+ NON_DISCOVERABLE_DEVICE *Device
)
{
EFI_STATUS Status;
@@ -103,454 +82,10 @@ ConfigureUSBHost (
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
ASSERT_EFI_ERROR (Status);
-}
-
-
-EFI_STATUS
-PciIoPollMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoPollIo (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoMemRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
- return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
- Count,
- Buffer
- );
-}
-
-EFI_STATUS
-PciIoMemWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
- return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
- Count,
- Buffer
- );
-}
-
-EFI_STATUS
-PciIoIoRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoIoWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-/**
- Enable a PCI driver to read PCI controller registers in PCI configuration space.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset within the PCI configuration space for
- the PCI controller.
- @param[in] Count The number of PCI configuration operations to
- perform. Bytes moved is Width size * Count,
- starting at Offset.
-
- @param[in out] Buffer The destination buffer to store the results.
-
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
-
-**/
-EFI_STATUS
-PciIoPciRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
- EFI_STATUS Status;
-
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = PciRootBridgeIoMemRW (
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
- Count,
- TRUE,
- (PTR)(UINTN)Buffer,
- TRUE,
- (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace
- );
-
- return Status;
-}
-
-/**
- Enable a PCI driver to write PCI controller registers in PCI configuration space.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset within the PCI configuration space for
- the PCI controller.
- @param[in] Count The number of PCI configuration operations to
- perform. Bytes moved is Width size * Count,
- starting at Offset.
-
- @param[in out] Buffer The source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
-
-**/
-EFI_STATUS
-PciIoPciWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Count,
- TRUE,
- (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
- TRUE,
- (PTR)(UINTN)Buffer
- );
-}
-
-EFI_STATUS
-PciIoCopyMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 DestBarIndex,
- IN UINT64 DestOffset,
- IN UINT8 SrcBarIndex,
- IN UINT64 SrcOffset,
- IN UINTN Count
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoMap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- )
-{
- DMA_MAP_OPERATION DmaOperation;
-
- if (Operation == EfiPciIoOperationBusMasterRead) {
- DmaOperation = MapOperationBusMasterRead;
- } else if (Operation == EfiPciIoOperationBusMasterWrite) {
- DmaOperation = MapOperationBusMasterWrite;
- } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
- DmaOperation = MapOperationBusMasterCommonBuffer;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
-}
-EFI_STATUS
-PciIoUnmap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN VOID *Mapping
- )
-{
- return DmaUnmap (Mapping);
-}
-
-/**
- Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
- mapping.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Type This parameter is not used and must be ignored.
- @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or
- EfiRuntimeServicesData.
- @param[in] Pages The number of pages to allocate.
- @param[out] HostAddress A pointer to store the base system memory address of
- the allocated range.
- @param[in] Attributes The requested bit mask of attributes for the allocated
- range. Only the attributes,
- EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
- EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this
- function. If any other bits are set, then EFI_UNSUPPORTED
- is returned. This function ignores this bit mask.
-
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_INVALID_PARAMETER MemoryType is invalid.
- @retval EFI_UNSUPPORTED Attributes is unsupported.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-PciIoAllocateBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- )
-{
- if (Attributes &
- (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
- EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) {
- return EFI_UNSUPPORTED;
- }
-
- return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFreeBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINTN Pages,
- IN VOID *HostAddress
- )
-{
- return DmaFreeBuffer (Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFlush (
- IN EFI_PCI_IO_PROTOCOL *This
- )
-{
return EFI_SUCCESS;
}
-/**
- Retrieves this PCI controller's current PCI bus number, device number, and function number.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[out] SegmentNumber The PCI controller's current PCI segment number.
- @param[out] BusNumber The PCI controller's current PCI bus number.
- @param[out] DeviceNumber The PCI controller's current PCI device number.
- @param[out] FunctionNumber The PCI controller's current PCI function number.
-
- @retval EFI_SUCCESS The PCI controller location was returned.
- @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is
- a NULL pointer.
-**/
-EFI_STATUS
-PciIoGetLocation (
- IN EFI_PCI_IO_PROTOCOL *This,
- OUT UINTN *SegmentNumber,
- OUT UINTN *BusNumber,
- OUT UINTN *DeviceNumber,
- OUT UINTN *FunctionNumber
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if ((SegmentNumber == NULL) || (BusNumber == NULL) ||
- (DeviceNumber == NULL) || (FunctionNumber == NULL) ) {
- return EFI_INVALID_PARAMETER;
- }
-
- *SegmentNumber = Private->Segment;
- *BusNumber = 0xff;
- *DeviceNumber = 0;
- *FunctionNumber = 0;
-
- return EFI_SUCCESS;
-}
-
-/**
- Performs an operation on the attributes that this PCI controller supports.
-
- The operations include getting the set of supported attributes, retrieving
- the current attributes, setting the current attributes, enabling attributes,
- and disabling attributes.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Operation The operation to perform on the attributes for this
- PCI controller.
- @param[in] Attributes The mask of attributes that are used for Set,
- Enable and Disable operations.
- @param[out] Result A pointer to the result mask of attributes that are
- returned for the Get and Supported operations. This
- is an optional parameter that may be NULL for the
- Set, Enable, and Disable operations.
-
- @retval EFI_SUCCESS The operation on the PCI controller's
- attributes was completed. If the operation
- was Get or Supported, then the attribute mask
- is returned in Result.
- @retval EFI_INVALID_PARAMETER Operation is greater than or equal to
- EfiPciIoAttributeOperationMaximum.
- @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL.
- @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL.
-
-**/
-EFI_STATUS
-PciIoAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
- IN UINT64 Attributes,
- OUT UINT64 *Result OPTIONAL
- )
-{
- switch (Operation) {
- case EfiPciIoAttributeOperationGet:
- case EfiPciIoAttributeOperationSupported:
- if (Result == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // We are not a real PCI device so just say things we kind of do
- //
- *Result = EFI_PCI_DEVICE_ENABLE;
- break;
-
- case EfiPciIoAttributeOperationSet:
- case EfiPciIoAttributeOperationEnable:
- case EfiPciIoAttributeOperationDisable:
- if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) {
- return EFI_UNSUPPORTED;
- }
- // Since we are not a real PCI device no enable/set or disable operations exist.
- return EFI_SUCCESS;
-
- default:
- return EFI_INVALID_PARAMETER;
- };
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciIoGetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT8 BarIndex,
- OUT UINT64 *Supports, OPTIONAL
- OUT VOID **Resources OPTIONAL
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoSetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN UINT8 BarIndex,
- IN OUT UINT64 *Offset,
- IN OUT UINT64 *Length
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_PCI_IO_PROTOCOL PciIoTemplate =
-{
- PciIoPollMem,
- PciIoPollIo,
- { PciIoMemRead, PciIoMemWrite },
- { PciIoIoRead, PciIoIoWrite },
- { PciIoPciRead, PciIoPciWrite },
- PciIoCopyMem,
- PciIoMap,
- PciIoUnmap,
- PciIoAllocateBuffer,
- PciIoFreeBuffer,
- PciIoFlush,
- PciIoGetLocation,
- PciIoAttributes,
- PciIoGetBarAttributes,
- PciIoSetBarAttributes,
- 0,
- 0
-};
-
EFI_STATUS
EFIAPI
PciEmulationEntryPoint (
@@ -558,76 +93,21 @@ PciEmulationEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_PCI_IO_PRIVATE_DATA *Private;
UINT8 CapabilityLength;
UINT8 PhysicalPorts;
- UINTN Count;
-
-
- //Configure USB host for OMAP3530.
- ConfigureUSBHost();
-
- // Create a private structure
- Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
- if (Private == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- return Status;
- }
-
- Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
- Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
- Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
- Private->Segment = 0; // Default to segment zero
-
- // Find out the capability register length and number of physical ports.
- CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
- PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
-
- // Calculate the total size of the USB registers.
- Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
-
- // Enable Port Power bit in Port status and control registers in EHCI register space.
- // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
- // host controller implementation includes port power control.
- for (Count = 0; Count < PhysicalPorts; Count++) {
- MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
- }
-
- // Create fake PCI config space.
- Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
- if (Private->ConfigSpace == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- FreePool(Private);
- return Status;
- }
-
- // Configure PCI config space
- Private->ConfigSpace->Hdr.VendorId = 0xFFFF; // Invalid vendor Id as it is not an actual device.
- Private->ConfigSpace->Hdr.DeviceId = 0x0000; // Not relevant as the vendor id is not valid.
- Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
- Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
- Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
- Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
-
- Handle = NULL;
-
- // Unique device path.
- CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
- Private->DevicePath.AcpiDevicePath.UID = 0;
-
- // Copy protocol structure
- CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
-
- Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
- &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
- &gEfiDevicePathProtocolGuid, &Private->DevicePath,
- NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
- }
-
- return Status;
+ UINTN MemorySize;
+
+ CapabilityLength = MmioRead8 (USB_EHCI_HCCAPBASE);
+ PhysicalPorts = MmioRead32 (USB_EHCI_HCCAPBASE + 0x4) & 0x0000000F;
+ MemorySize = CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE +
+ 4 * PhysicalPorts - 1;
+
+ return RegisterNonDiscoverableMmioDevice (
+ NonDiscoverableDeviceTypeEhci,
+ NonDiscoverableDeviceDmaTypeNonCoherent,
+ ConfigureUSBHost,
+ NULL,
+ 1,
+ USB_EHCI_HCCAPBASE, MemorySize
+ );
}
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.h b/Omap35xxPkg/PciEmulation/PciEmulation.h
deleted file mode 100644
index d5ee04318939..000000000000
--- a/Omap35xxPkg/PciEmulation/PciEmulation.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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.
-
-**/
-
-#ifndef _PCI_ROOT_BRIDGE_H_
-#define _PCI_ROOT_BRIDGE_H_
-
-#include <PiDxe.h>
-
-#include <TPS65950.h>
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/IoLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PciLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/OmapDmaLib.h>
-#include <Library/DmaLib.h>
-
-#include <Protocol/EmbeddedExternalDevice.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/PciHostBridgeResourceAllocation.h>
-
-#include <IndustryStandard/Pci22.h>
-#include <IndustryStandard/Acpi.h>
-
-#include <Omap3530/Omap3530.h>
-
-
-
-#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
-#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
-#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
-
-
-typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
-} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
-
-
-#define ACPI_CONFIG_IO 0
-#define ACPI_CONFIG_MMIO 1
-#define ACPI_CONFIG_BUS 2
-
-typedef struct {
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
- EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
-} ACPI_CONFIG_INFO;
-
-
-#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
-
-typedef struct {
- UINT32 Signature;
- EFI_HANDLE Handle;
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
- EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
-
- UINT8 StartBus;
- UINT8 EndBus;
- UINT16 Type;
- UINT32 MemoryStart;
- UINT32 MemorySize;
- UINTN IoOffset;
- UINT32 IoStart;
- UINT32 IoSize;
- UINT64 PciAttributes;
-
- ACPI_CONFIG_INFO *Config;
-
-} PCI_ROOT_BRIDGE;
-
-
-#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
-
-
-typedef union {
- UINT8 volatile *buf;
- UINT8 volatile *ui8;
- UINT16 volatile *ui16;
- UINT32 volatile *ui32;
- UINT64 volatile *ui64;
- UINTN volatile ui;
-} PTR;
-
-
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollIo (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoCopyMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 DestAddress,
- IN UINT64 SrcAddress,
- IN UINTN Count
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoUnmap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN VOID *Mapping
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoAllocateBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFreeBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINTN Pages,
- OUT VOID *HostAddress
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFlush (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoGetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT UINT64 *Supported,
- OUT UINT64 *Attributes
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoSetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN OUT UINT64 *ResourceBase,
- IN OUT UINT64 *ResourceLength
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoConfiguration (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT VOID **Resources
- );
-
-//
-// Private Function Prototypes
-//
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- );
-
-BOOLEAN
-PciIoMemAddressValid (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Address
- );
-
-EFI_STATUS
-EmulatePciIoForEhci (
- INTN MvPciIfMaxIf
- );
-
-#endif
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.inf b/Omap35xxPkg/PciEmulation/PciEmulation.inf
index 2180bb49898d..4df9c505e8cd 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.inf
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.inf
@@ -22,33 +22,23 @@ [Defines]
ENTRY_POINT = PciEmulationEntryPoint
[Sources.common]
- PciRootBridgeIo.c
PciEmulation.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
- IntelFrameworkPkg/IntelFrameworkPkg.dec
- ArmPkg/ArmPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
Omap35xxPkg/Omap35xxPkg.dec
[LibraryClasses]
BaseLib
- DxeServicesTableLib
- UefiLib
+ DebugLib
+ IoLib
+ NonDiscoverableDeviceRegistrationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
- UefiRuntimeServicesTableLib
- IoLib
- OmapDmaLib
- DmaLib
[Protocols]
- gEfiPciRootBridgeIoProtocolGuid
- gEfiDevicePathProtocolGuid
- gEfiPciHostBridgeResourceAllocationProtocolGuid
- gEfiPciIoProtocolGuid
gEmbeddedExternalDeviceProtocolGuid
[Depex]
diff --git a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
deleted file mode 100644
index e8635ed88d91..000000000000
--- a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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 "PciEmulation.h"
-
-BOOLEAN
-PciRootBridgeMemAddressValid (
- IN PCI_ROOT_BRIDGE *Private,
- IN UINT64 Address
- )
-{
- if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-EFI_STATUS
-PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- )
-{
- UINTN Stride;
- UINTN InStride;
- UINTN OutStride;
-
-
- Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
- Stride = (UINTN)1 << Width;
- InStride = InStrideFlag ? Stride : 0;
- OutStride = OutStrideFlag ? Stride : 0;
-
- //
- // Loop for each iteration and move the data
- //
- switch (Width) {
- case EfiPciWidthUint8:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui8 = *Out.ui8;
- }
- break;
- case EfiPciWidthUint16:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui16 = *Out.ui16;
- }
- break;
- case EfiPciWidthUint32:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui32 = *Out.ui32;
- }
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciRootBridgeIoPciRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN BOOLEAN Write,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- )
-{
- return EFI_SUCCESS;
-}
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
-
- if ( Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
-
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
-
- In.buf = Buffer;
- Out.buf = (VOID *)(UINTN) Address;
-
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
- default:
- break;
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
-
- if ( Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
-
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
-
- In.buf = (VOID *)(UINTN) Address;
- Out.buf = Buffer;
-
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
- default:
- break;
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
@ 2016-12-14 9:15 ` Ard Biesheuvel
2016-12-15 8:17 ` Ni, Ruiyu
1 sibling, 0 replies; 6+ messages in thread
From: Ard Biesheuvel @ 2016-12-14 9:15 UTC (permalink / raw)
To: edk2-devel@lists.01.org, Leif Lindholm, Ruiyu Ni
Cc: Tian, Feng, Gao, Liming, Ard Biesheuvel
Ray,
Do you have any comments on this version?
Thanks,
Ard.
On 9 December 2016 at 15:04, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Add support for non-coherent DMA, either by performing explicit cache
> maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment,
> or by bounce buffering via uncached mappings otherwise.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Tested-by: Marcin Wojtas <mw@semihalf.com>
> ---
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +-
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 +
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 ++++++++++++++++++++
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 ++
> 4 files changed, 367 insertions(+), 7 deletions(-)
>
> diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
> index ee765d7a5d9c..0fcf2b2ec1bf 100644
> --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
> +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
> @@ -16,6 +16,8 @@
>
> #include <Protocol/DriverBinding.h>
>
> +EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> //
> // We only support the following device types
> //
> @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported (
> return Status;
> }
>
> - //
> - // Restricted to DMA coherent for now
> - //
> Status = EFI_UNSUPPORTED;
> - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
> - goto CloseProtocol;
> - }
> -
> for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
> if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
> Status = EFI_SUCCESS;
> @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
> IN EFI_SYSTEM_TABLE *SystemTable
> )
> {
> + EFI_STATUS Status;
> +
> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
> + ASSERT_EFI_ERROR(Status);
> +
> return EfiLibInstallDriverBindingComponentName2 (
> ImageHandle,
> SystemTable,
> diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
> index 996fe310e0e3..5faa8945134c 100644
> --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
> @@ -32,6 +32,7 @@ [Packages]
> [LibraryClasses]
> BaseMemoryLib
> DebugLib
> + DxeServicesTableLib
> MemoryAllocationLib
> UefiBootServicesTableLib
> UefiDriverEntryPoint
> @@ -40,6 +41,7 @@ [LibraryClasses]
> [Protocols]
> gEfiPciIoProtocolGuid ## BY_START
> gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
> + gEfiCpuArchProtocolGuid ## CONSUMES
>
> [Guids]
> gEdkiiNonDiscoverableAhciDeviceGuid
> diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
> index 56482e3353c0..814f7643ae4c 100644
> --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
> +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
> @@ -15,6 +15,8 @@
>
> #include "NonDiscoverablePciDeviceIo.h"
>
> +#include <Library/DxeServicesTableLib.h>
> +
> #include <IndustryStandard/Acpi.h>
>
> #include <Protocol/PciRootBridgeIo.h>
> @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer (
> return EFI_SUCCESS;
> }
>
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoFreeBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINTN Pages,
> + IN VOID *HostAddress
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + LIST_ENTRY *Entry;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> + BOOLEAN Found;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Found = FALSE;
> +
> + //
> + // Find the uncached allocation list entry associated
> + // with this allocation
> + //
> + for (Entry = Dev->UncachedAllocationList.ForwardLink;
> + Entry != &Dev->UncachedAllocationList;
> + Entry = Entry->ForwardLink) {
> +
> + Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
> + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
> + //
> + // We are freeing the exact allocation we were given
> + // before by AllocateBuffer()
> + //
> + Found = TRUE;
> + break;
> + }
> + }
> +
> + if (!Found) {
> + ASSERT_EFI_ERROR (EFI_NOT_FOUND);
> + return EFI_NOT_FOUND;
> + }
> +
> + RemoveEntryList (&Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + Alloc->Attributes);
> + if (EFI_ERROR (Status)) {
> + goto FreeAlloc;
> + }
> +
> + //
> + // If we fail to restore the original attributes, it is better to leak the
> + // memory than to return it to the heap
> + //
> + FreePages (HostAddress, Pages);
> +
> +FreeAlloc:
> + FreePool (Alloc);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoAllocateBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_ALLOCATE_TYPE Type,
> + IN EFI_MEMORY_TYPE MemoryType,
> + IN UINTN Pages,
> + OUT VOID **HostAddress,
> + IN UINT64 Attributes
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + EFI_STATUS Status;
> + UINT64 MemType;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> + VOID *AllocAddress;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
> + &AllocAddress, Attributes);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status)) {
> + goto FreeBuffer;
> + }
> +
> + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) {
> + Status = EFI_UNSUPPORTED;
> + goto FreeBuffer;
> + }
> +
> + //
> + // Set the preferred memory attributes
> + //
> + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
> + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
> + //
> + // Use write combining if it was requested, or if it is the only
> + // type supported by the region.
> + //
> + MemType = EFI_MEMORY_WC;
> + } else {
> + MemType = EFI_MEMORY_UC;
> + }
> +
> + Alloc = AllocatePool (sizeof *Alloc);
> + if (Alloc == NULL) {
> + goto FreeBuffer;
> + }
> +
> + Alloc->HostAddress = AllocAddress;
> + Alloc->NumPages = Pages;
> + Alloc->Attributes = GcdDescriptor.Attributes;
> +
> + //
> + // Record this allocation in the linked list, so we
> + // can restore the memory space attributes later
> + //
> + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + MemType);
> + if (EFI_ERROR (Status)) {
> + goto RemoveList;
> + }
> +
> + Status = mCpu->FlushDataCache (
> + mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + EfiCpuFlushTypeInvalidate);
> + if (EFI_ERROR (Status)) {
> + goto RemoveList;
> + }
> +
> + *HostAddress = AllocAddress;
> +
> + return EFI_SUCCESS;
> +
> +RemoveList:
> + RemoveEntryList (&Alloc->List);
> + FreePool (Alloc);
> +
> +FreeBuffer:
> + CoherentPciIoFreeBuffer (This, Pages, AllocAddress);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoMap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
> + IN VOID *HostAddress,
> + IN OUT UINTN *NumberOfBytes,
> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> + OUT VOID **Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> + UINTN AlignMask;
> + VOID *AllocAddress;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + BOOLEAN Bounce;
> +
> + MapInfo = AllocatePool (sizeof *MapInfo);
> + if (MapInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MapInfo->HostAddress = HostAddress;
> + MapInfo->Operation = Operation;
> + MapInfo->NumberOfBytes = *NumberOfBytes;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + //
> + // If this device does not support 64-bit DMA addressing, we need to allocate
> + // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
> + //
> + Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
> +
> + if (!Bounce) {
> + switch (Operation) {
> + case EfiPciIoOperationBusMasterRead:
> + case EfiPciIoOperationBusMasterWrite:
> + //
> + // For streaming DMA, it is sufficient if the buffer is aligned to
> + // the CPUs DMA buffer alignment.
> + //
> + AlignMask = mCpu->DmaBufferAlignment - 1;
> + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
> + break;
> + }
> + // fall through
> +
> + case EfiPciIoOperationBusMasterCommonBuffer:
> + //
> + // Check whether the host address refers to an uncached mapping.
> + //
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status) ||
> + (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
> + Bounce = TRUE;
> + }
> + break;
> +
> + default:
> + ASSERT (FALSE);
> + }
> + }
> +
> + if (Bounce) {
> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
> + Status = EFI_DEVICE_ERROR;
> + goto FreeMapInfo;
> + }
> +
> + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
> + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
> + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
> + if (EFI_ERROR (Status)) {
> + goto FreeMapInfo;
> + }
> + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
> + if (Operation == EfiPciIoOperationBusMasterRead) {
> + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
> + }
> + *DeviceAddress = MapInfo->AllocAddress;
> + } else {
> + MapInfo->AllocAddress = 0;
> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
> +
> + //
> + // We are not using a bounce buffer: the mapping is sufficiently
> + // aligned to allow us to simply flush the caches. Note that cleaning
> + // the caches is necessary for both data directions:
> + // - for bus master read, we want the latest data to be present
> + // in main memory
> + // - for bus master write, we don't want any stale dirty cachelines that
> + // may be written back unexpectedly, and clobber the data written to
> + // main memory by the device.
> + //
> + mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + *NumberOfBytes, EfiCpuFlushTypeWriteBack);
> + }
> +
> + *Mapping = MapInfo;
> + return EFI_SUCCESS;
> +
> +FreeMapInfo:
> + FreePool (MapInfo);
> +
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoUnmap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN VOID *Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> +
> + if (Mapping == NULL) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + MapInfo = Mapping;
> + if (MapInfo->AllocAddress != 0) {
> + //
> + // We are using a bounce buffer: copy back the data if necessary,
> + // and free the buffer.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,
> + MapInfo->NumberOfBytes);
> + }
> + NonCoherentPciIoFreeBuffer (This,
> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
> + (VOID *)(UINTN)MapInfo->AllocAddress);
> + } else {
> + //
> + // We are *not* using a bounce buffer: if this is a bus master write,
> + // we have to invalidate the caches so the CPU will see the uncached
> + // data written by the device.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + mCpu->FlushDataCache (mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
> + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
> + }
> + }
> + FreePool (MapInfo);
> + return EFI_SUCCESS;
> +}
>
> STATIC
> EFI_STATUS
> @@ -726,12 +1046,21 @@ InitializePciIoProtocol (
> EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> INTN Idx;
>
> + InitializeListHead (&Dev->UncachedAllocationList);
> +
> Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
> Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
>
> // Copy protocol structure
> CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
>
> + if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
> + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
> + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
> + Dev->PciIo.Map = NonCoherentPciIoMap;
> + Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
> + }
> +
> if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {
> Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
> Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;
> diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
> index bc0a3d3258f9..449614862911 100644
> --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
> +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
> @@ -15,6 +15,8 @@
> #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>
> +#include <PiDxe.h>
> +
> #include <Library/BaseMemoryLib.h>
> #include <Library/DebugLib.h>
> #include <Library/MemoryAllocationLib.h>
> @@ -25,6 +27,7 @@
>
> #include <Protocol/ComponentName.h>
> #include <Protocol/NonDiscoverableDevice.h>
> +#include <Protocol/Cpu.h>
> #include <Protocol/PciIo.h>
>
> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D')
> @@ -38,6 +41,27 @@
>
> #define PCI_MAX_BARS 6
>
> +extern EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> +typedef struct {
> + //
> + // The linked-list next pointer
> + //
> + LIST_ENTRY List;
> + //
> + // The address of the uncached allocation
> + //
> + VOID *HostAddress;
> + //
> + // The number of pages in the allocation
> + //
> + UINTN NumPages;
> + //
> + // The attributes of the allocation
> + //
> + UINT64 Attributes;
> +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
> +
> typedef struct {
> UINT32 Signature;
> //
> @@ -71,6 +95,11 @@ typedef struct {
> // Whether this device has been enabled
> //
> BOOLEAN Enabled;
> + //
> + // Linked list to keep track of uncached allocations performed
> + // on behalf of this device
> + //
> + LIST_ENTRY UncachedAllocationList;
> } NON_DISCOVERABLE_PCI_DEVICE;
>
> VOID
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
2016-12-14 9:15 ` Ard Biesheuvel
@ 2016-12-15 8:17 ` Ni, Ruiyu
2016-12-15 8:22 ` Ard Biesheuvel
1 sibling, 1 reply; 6+ messages in thread
From: Ni, Ruiyu @ 2016-12-15 8:17 UTC (permalink / raw)
To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org
Cc: Tian, Feng, Gao, Liming
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ard Biesheuvel
> Sent: Friday, December 9, 2016 11:05 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Ni, Ruiyu
> <ruiyu.ni@intel.com>
> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [edk2] [PATCH v6 1/2]
> MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-
> coherent DMA
>
> Add support for non-coherent DMA, either by performing explicit cache
> maintenance when DMA mappings are aligned to the CPU's DMA buffer
> alignment,
> or by bounce buffering via uncached mappings otherwise.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Tested-by: Marcin Wojtas <mw@semihalf.com>
> ---
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.c | 14 +-
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.inf | 2 +
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.c | 329 ++++++++++++++++++++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.h | 29 ++
> 4 files changed, 367 insertions(+), 7 deletions(-)
>
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> index ee765d7a5d9c..0fcf2b2ec1bf 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> @@ -16,6 +16,8 @@
>
> #include <Protocol/DriverBinding.h>
>
> +EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> //
> // We only support the following device types
> //
> @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported (
> return Status;
> }
>
> - //
> - // Restricted to DMA coherent for now
> - //
> Status = EFI_UNSUPPORTED;
> - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
> - goto CloseProtocol;
> - }
> -
> for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++)
> {
> if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx]))
> {
> Status = EFI_SUCCESS;
> @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
> IN EFI_SYSTEM_TABLE *SystemTable
> )
> {
> + EFI_STATUS Status;
> +
> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID
> **)&mCpu);
> + ASSERT_EFI_ERROR(Status);
> +
> return EfiLibInstallDriverBindingComponentName2 (
> ImageHandle,
> SystemTable,
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> index 996fe310e0e3..5faa8945134c 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> @@ -32,6 +32,7 @@ [Packages]
> [LibraryClasses]
> BaseMemoryLib
> DebugLib
> + DxeServicesTableLib
> MemoryAllocationLib
> UefiBootServicesTableLib
> UefiDriverEntryPoint
> @@ -40,6 +41,7 @@ [LibraryClasses]
> [Protocols]
> gEfiPciIoProtocolGuid ## BY_START
> gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
> + gEfiCpuArchProtocolGuid ## CONSUMES
>
> [Guids]
> gEdkiiNonDiscoverableAhciDeviceGuid
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> index 56482e3353c0..814f7643ae4c 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> @@ -15,6 +15,8 @@
>
> #include "NonDiscoverablePciDeviceIo.h"
>
> +#include <Library/DxeServicesTableLib.h>
> +
> #include <IndustryStandard/Acpi.h>
>
> #include <Protocol/PciRootBridgeIo.h>
> @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer (
> return EFI_SUCCESS;
> }
>
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoFreeBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINTN Pages,
> + IN VOID *HostAddress
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + LIST_ENTRY *Entry;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> + BOOLEAN Found;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Found = FALSE;
> +
> + //
> + // Find the uncached allocation list entry associated
> + // with this allocation
> + //
> + for (Entry = Dev->UncachedAllocationList.ForwardLink;
> + Entry != &Dev->UncachedAllocationList;
> + Entry = Entry->ForwardLink) {
> +
> + Alloc = BASE_CR (Entry,
> NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
> + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
> + //
> + // We are freeing the exact allocation we were given
> + // before by AllocateBuffer()
> + //
> + Found = TRUE;
> + break;
> + }
> + }
> +
> + if (!Found) {
> + ASSERT_EFI_ERROR (EFI_NOT_FOUND);
> + return EFI_NOT_FOUND;
> + }
> +
> + RemoveEntryList (&Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + Alloc->Attributes);
> + if (EFI_ERROR (Status)) {
> + goto FreeAlloc;
> + }
> +
> + //
> + // If we fail to restore the original attributes, it is better to leak the
> + // memory than to return it to the heap
> + //
> + FreePages (HostAddress, Pages);
> +
> +FreeAlloc:
> + FreePool (Alloc);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoAllocateBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_ALLOCATE_TYPE Type,
> + IN EFI_MEMORY_TYPE MemoryType,
> + IN UINTN Pages,
> + OUT VOID **HostAddress,
> + IN UINT64 Attributes
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + EFI_STATUS Status;
> + UINT64 MemType;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> + VOID *AllocAddress;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
> + &AllocAddress, Attributes);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status)) {
> + goto FreeBuffer;
> + }
> +
> + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC))
> == 0) {
> + Status = EFI_UNSUPPORTED;
> + goto FreeBuffer;
> + }
> +
> + //
> + // Set the preferred memory attributes
> + //
> + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
> + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
> + //
> + // Use write combining if it was requested, or if it is the only
> + // type supported by the region.
> + //
> + MemType = EFI_MEMORY_WC;
> + } else {
> + MemType = EFI_MEMORY_UC;
> + }
> +
> + Alloc = AllocatePool (sizeof *Alloc);
> + if (Alloc == NULL) {
> + goto FreeBuffer;
> + }
> +
> + Alloc->HostAddress = AllocAddress;
> + Alloc->NumPages = Pages;
> + Alloc->Attributes = GcdDescriptor.Attributes;
> +
> + //
> + // Record this allocation in the linked list, so we
> + // can restore the memory space attributes later
> + //
> + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + MemType);
> + if (EFI_ERROR (Status)) {
> + goto RemoveList;
> + }
> +
> + Status = mCpu->FlushDataCache (
> + mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + EfiCpuFlushTypeInvalidate);
> + if (EFI_ERROR (Status)) {
> + goto RemoveList;
> + }
> +
> + *HostAddress = AllocAddress;
> +
> + return EFI_SUCCESS;
> +
> +RemoveList:
> + RemoveEntryList (&Alloc->List);
> + FreePool (Alloc);
> +
> +FreeBuffer:
> + CoherentPciIoFreeBuffer (This, Pages, AllocAddress);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoMap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
> + IN VOID *HostAddress,
> + IN OUT UINTN *NumberOfBytes,
> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> + OUT VOID **Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> + UINTN AlignMask;
> + VOID *AllocAddress;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + BOOLEAN Bounce;
> +
> + MapInfo = AllocatePool (sizeof *MapInfo);
> + if (MapInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MapInfo->HostAddress = HostAddress;
> + MapInfo->Operation = Operation;
> + MapInfo->NumberOfBytes = *NumberOfBytes;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + //
> + // If this device does not support 64-bit DMA addressing, we need to
> allocate
> + // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
> + //
> + Bounce = ((Dev->Attributes &
> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
> +
> + if (!Bounce) {
> + switch (Operation) {
> + case EfiPciIoOperationBusMasterRead:
> + case EfiPciIoOperationBusMasterWrite:
> + //
> + // For streaming DMA, it is sufficient if the buffer is aligned to
> + // the CPUs DMA buffer alignment.
> + //
> + AlignMask = mCpu->DmaBufferAlignment - 1;
> + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
> + break;
> + }
> + // fall through
> +
> + case EfiPciIoOperationBusMasterCommonBuffer:
> + //
> + // Check whether the host address refers to an uncached mapping.
> + //
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status) ||
> + (GcdDescriptor.Attributes &
> (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
> + Bounce = TRUE;
> + }
> + break;
> +
> + default:
> + ASSERT (FALSE);
> + }
> + }
> +
> + if (Bounce) {
> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
> + Status = EFI_DEVICE_ERROR;
> + goto FreeMapInfo;
> + }
> +
> + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
> + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo-
> >NumberOfBytes),
> + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
> + if (EFI_ERROR (Status)) {
> + goto FreeMapInfo;
> + }
> + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
> + if (Operation == EfiPciIoOperationBusMasterRead) {
> + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
> + }
> + *DeviceAddress = MapInfo->AllocAddress;
> + } else {
> + MapInfo->AllocAddress = 0;
> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
> +
> + //
> + // We are not using a bounce buffer: the mapping is sufficiently
> + // aligned to allow us to simply flush the caches. Note that cleaning
> + // the caches is necessary for both data directions:
> + // - for bus master read, we want the latest data to be present
> + // in main memory
> + // - for bus master write, we don't want any stale dirty cachelines that
> + // may be written back unexpectedly, and clobber the data written to
> + // main memory by the device.
> + //
> + mCpu->FlushDataCache (mCpu,
> (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + *NumberOfBytes, EfiCpuFlushTypeWriteBack);
> + }
> +
> + *Mapping = MapInfo;
> + return EFI_SUCCESS;
> +
> +FreeMapInfo:
> + FreePool (MapInfo);
> +
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonCoherentPciIoUnmap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN VOID *Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> +
> + if (Mapping == NULL) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + MapInfo = Mapping;
> + if (MapInfo->AllocAddress != 0) {
> + //
> + // We are using a bounce buffer: copy back the data if necessary,
> + // and free the buffer.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo-
> >AllocAddress,
> + MapInfo->NumberOfBytes);
> + }
> + NonCoherentPciIoFreeBuffer (This,
> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
> + (VOID *)(UINTN)MapInfo->AllocAddress);
> + } else {
> + //
> + // We are *not* using a bounce buffer: if this is a bus master write,
> + // we have to invalidate the caches so the CPU will see the uncached
> + // data written by the device.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + mCpu->FlushDataCache (mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
> + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
> + }
> + }
> + FreePool (MapInfo);
> + return EFI_SUCCESS;
> +}
>
> STATIC
> EFI_STATUS
> @@ -726,12 +1046,21 @@ InitializePciIoProtocol (
> EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> INTN Idx;
>
> + InitializeListHead (&Dev->UncachedAllocationList);
> +
> Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
> Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
>
> // Copy protocol structure
> CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
>
> + if (Dev->Device->DmaType ==
> NonDiscoverableDeviceDmaTypeNonCoherent) {
> + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
> + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
> + Dev->PciIo.Map = NonCoherentPciIoMap;
> + Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
> + }
> +
> if (CompareGuid (Dev->Device->Type,
> &gEdkiiNonDiscoverableAhciDeviceGuid)) {
> Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
> Dev->ConfigSpace.Hdr.ClassCode[1] =
> PCI_CLASS_MASS_STORAGE_SATADPA;
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> index bc0a3d3258f9..449614862911 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> @@ -15,6 +15,8 @@
> #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>
> +#include <PiDxe.h>
> +
> #include <Library/BaseMemoryLib.h>
> #include <Library/DebugLib.h>
> #include <Library/MemoryAllocationLib.h>
> @@ -25,6 +27,7 @@
>
> #include <Protocol/ComponentName.h>
> #include <Protocol/NonDiscoverableDevice.h>
> +#include <Protocol/Cpu.h>
> #include <Protocol/PciIo.h>
>
> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> 'D')
> @@ -38,6 +41,27 @@
>
> #define PCI_MAX_BARS 6
>
> +extern EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> +typedef struct {
> + //
> + // The linked-list next pointer
> + //
> + LIST_ENTRY List;
> + //
> + // The address of the uncached allocation
> + //
> + VOID *HostAddress;
> + //
> + // The number of pages in the allocation
> + //
> + UINTN NumPages;
> + //
> + // The attributes of the allocation
> + //
> + UINT64 Attributes;
> +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
> +
> typedef struct {
> UINT32 Signature;
> //
> @@ -71,6 +95,11 @@ typedef struct {
> // Whether this device has been enabled
> //
> BOOLEAN Enabled;
> + //
> + // Linked list to keep track of uncached allocations performed
> + // on behalf of this device
> + //
> + LIST_ENTRY UncachedAllocationList;
> } NON_DISCOVERABLE_PCI_DEVICE;
>
> VOID
> --
> 2.7.4
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-12-15 8:17 ` Ni, Ruiyu
@ 2016-12-15 8:22 ` Ard Biesheuvel
0 siblings, 0 replies; 6+ messages in thread
From: Ard Biesheuvel @ 2016-12-15 8:22 UTC (permalink / raw)
To: Ni, Ruiyu
Cc: edk2-devel@lists.01.org, leif.lindholm@linaro.org, Tian, Feng,
Gao, Liming
On 15 December 2016 at 08:17, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>
> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Pushed, thanks.
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>> Ard Biesheuvel
>> Sent: Friday, December 9, 2016 11:05 PM
>> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Ni, Ruiyu
>> <ruiyu.ni@intel.com>
>> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>;
>> Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Subject: [edk2] [PATCH v6 1/2]
>> MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-
>> coherent DMA
>>
>> Add support for non-coherent DMA, either by performing explicit cache
>> maintenance when DMA mappings are aligned to the CPU's DMA buffer
>> alignment,
>> or by bounce buffering via uncached mappings otherwise.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Tested-by: Marcin Wojtas <mw@semihalf.com>
>> ---
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceDxe.c | 14 +-
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceDxe.inf | 2 +
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceIo.c | 329 ++++++++++++++++++++
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceIo.h | 29 ++
>> 4 files changed, 367 insertions(+), 7 deletions(-)
>>
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.c
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.c
>> index ee765d7a5d9c..0fcf2b2ec1bf 100644
>> ---
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.c
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.c
>> @@ -16,6 +16,8 @@
>>
>> #include <Protocol/DriverBinding.h>
>>
>> +EFI_CPU_ARCH_PROTOCOL *mCpu;
>> +
>> //
>> // We only support the following device types
>> //
>> @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported (
>> return Status;
>> }
>>
>> - //
>> - // Restricted to DMA coherent for now
>> - //
>> Status = EFI_UNSUPPORTED;
>> - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
>> - goto CloseProtocol;
>> - }
>> -
>> for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++)
>> {
>> if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx]))
>> {
>> Status = EFI_SUCCESS;
>> @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
>> IN EFI_SYSTEM_TABLE *SystemTable
>> )
>> {
>> + EFI_STATUS Status;
>> +
>> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID
>> **)&mCpu);
>> + ASSERT_EFI_ERROR(Status);
>> +
>> return EfiLibInstallDriverBindingComponentName2 (
>> ImageHandle,
>> SystemTable,
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.inf
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.inf
>> index 996fe310e0e3..5faa8945134c 100644
>> ---
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.inf
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceDxe.inf
>> @@ -32,6 +32,7 @@ [Packages]
>> [LibraryClasses]
>> BaseMemoryLib
>> DebugLib
>> + DxeServicesTableLib
>> MemoryAllocationLib
>> UefiBootServicesTableLib
>> UefiDriverEntryPoint
>> @@ -40,6 +41,7 @@ [LibraryClasses]
>> [Protocols]
>> gEfiPciIoProtocolGuid ## BY_START
>> gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
>> + gEfiCpuArchProtocolGuid ## CONSUMES
>>
>> [Guids]
>> gEdkiiNonDiscoverableAhciDeviceGuid
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> index 56482e3353c0..814f7643ae4c 100644
>> ---
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> @@ -15,6 +15,8 @@
>>
>> #include "NonDiscoverablePciDeviceIo.h"
>>
>> +#include <Library/DxeServicesTableLib.h>
>> +
>> #include <IndustryStandard/Acpi.h>
>>
>> #include <Protocol/PciRootBridgeIo.h>
>> @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer (
>> return EFI_SUCCESS;
>> }
>>
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +NonCoherentPciIoFreeBuffer (
>> + IN EFI_PCI_IO_PROTOCOL *This,
>> + IN UINTN Pages,
>> + IN VOID *HostAddress
>> + )
>> +{
>> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
>> + LIST_ENTRY *Entry;
>> + EFI_STATUS Status;
>> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
>> + BOOLEAN Found;
>> +
>> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> + Found = FALSE;
>> +
>> + //
>> + // Find the uncached allocation list entry associated
>> + // with this allocation
>> + //
>> + for (Entry = Dev->UncachedAllocationList.ForwardLink;
>> + Entry != &Dev->UncachedAllocationList;
>> + Entry = Entry->ForwardLink) {
>> +
>> + Alloc = BASE_CR (Entry,
>> NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
>> + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
>> + //
>> + // We are freeing the exact allocation we were given
>> + // before by AllocateBuffer()
>> + //
>> + Found = TRUE;
>> + break;
>> + }
>> + }
>> +
>> + if (!Found) {
>> + ASSERT_EFI_ERROR (EFI_NOT_FOUND);
>> + return EFI_NOT_FOUND;
>> + }
>> +
>> + RemoveEntryList (&Alloc->List);
>> +
>> + Status = gDS->SetMemorySpaceAttributes (
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
>> + EFI_PAGES_TO_SIZE (Pages),
>> + Alloc->Attributes);
>> + if (EFI_ERROR (Status)) {
>> + goto FreeAlloc;
>> + }
>> +
>> + //
>> + // If we fail to restore the original attributes, it is better to leak the
>> + // memory than to return it to the heap
>> + //
>> + FreePages (HostAddress, Pages);
>> +
>> +FreeAlloc:
>> + FreePool (Alloc);
>> + return Status;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +NonCoherentPciIoAllocateBuffer (
>> + IN EFI_PCI_IO_PROTOCOL *This,
>> + IN EFI_ALLOCATE_TYPE Type,
>> + IN EFI_MEMORY_TYPE MemoryType,
>> + IN UINTN Pages,
>> + OUT VOID **HostAddress,
>> + IN UINT64 Attributes
>> + )
>> +{
>> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
>> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
>> + EFI_STATUS Status;
>> + UINT64 MemType;
>> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
>> + VOID *AllocAddress;
>> +
>> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
>> + &AllocAddress, Attributes);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = gDS->GetMemorySpaceDescriptor (
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
>> + &GcdDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + goto FreeBuffer;
>> + }
>> +
>> + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC))
>> == 0) {
>> + Status = EFI_UNSUPPORTED;
>> + goto FreeBuffer;
>> + }
>> +
>> + //
>> + // Set the preferred memory attributes
>> + //
>> + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
>> + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
>> + //
>> + // Use write combining if it was requested, or if it is the only
>> + // type supported by the region.
>> + //
>> + MemType = EFI_MEMORY_WC;
>> + } else {
>> + MemType = EFI_MEMORY_UC;
>> + }
>> +
>> + Alloc = AllocatePool (sizeof *Alloc);
>> + if (Alloc == NULL) {
>> + goto FreeBuffer;
>> + }
>> +
>> + Alloc->HostAddress = AllocAddress;
>> + Alloc->NumPages = Pages;
>> + Alloc->Attributes = GcdDescriptor.Attributes;
>> +
>> + //
>> + // Record this allocation in the linked list, so we
>> + // can restore the memory space attributes later
>> + //
>> + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
>> +
>> + Status = gDS->SetMemorySpaceAttributes (
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
>> + EFI_PAGES_TO_SIZE (Pages),
>> + MemType);
>> + if (EFI_ERROR (Status)) {
>> + goto RemoveList;
>> + }
>> +
>> + Status = mCpu->FlushDataCache (
>> + mCpu,
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
>> + EFI_PAGES_TO_SIZE (Pages),
>> + EfiCpuFlushTypeInvalidate);
>> + if (EFI_ERROR (Status)) {
>> + goto RemoveList;
>> + }
>> +
>> + *HostAddress = AllocAddress;
>> +
>> + return EFI_SUCCESS;
>> +
>> +RemoveList:
>> + RemoveEntryList (&Alloc->List);
>> + FreePool (Alloc);
>> +
>> +FreeBuffer:
>> + CoherentPciIoFreeBuffer (This, Pages, AllocAddress);
>> + return Status;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +NonCoherentPciIoMap (
>> + IN EFI_PCI_IO_PROTOCOL *This,
>> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
>> + IN VOID *HostAddress,
>> + IN OUT UINTN *NumberOfBytes,
>> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
>> + OUT VOID **Mapping
>> + )
>> +{
>> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
>> + EFI_STATUS Status;
>> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
>> + UINTN AlignMask;
>> + VOID *AllocAddress;
>> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
>> + BOOLEAN Bounce;
>> +
>> + MapInfo = AllocatePool (sizeof *MapInfo);
>> + if (MapInfo == NULL) {
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + MapInfo->HostAddress = HostAddress;
>> + MapInfo->Operation = Operation;
>> + MapInfo->NumberOfBytes = *NumberOfBytes;
>> +
>> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> + //
>> + // If this device does not support 64-bit DMA addressing, we need to
>> allocate
>> + // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
>> + //
>> + Bounce = ((Dev->Attributes &
>> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
>> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
>> +
>> + if (!Bounce) {
>> + switch (Operation) {
>> + case EfiPciIoOperationBusMasterRead:
>> + case EfiPciIoOperationBusMasterWrite:
>> + //
>> + // For streaming DMA, it is sufficient if the buffer is aligned to
>> + // the CPUs DMA buffer alignment.
>> + //
>> + AlignMask = mCpu->DmaBufferAlignment - 1;
>> + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
>> + break;
>> + }
>> + // fall through
>> +
>> + case EfiPciIoOperationBusMasterCommonBuffer:
>> + //
>> + // Check whether the host address refers to an uncached mapping.
>> + //
>> + Status = gDS->GetMemorySpaceDescriptor (
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
>> + &GcdDescriptor);
>> + if (EFI_ERROR (Status) ||
>> + (GcdDescriptor.Attributes &
>> (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
>> + Bounce = TRUE;
>> + }
>> + break;
>> +
>> + default:
>> + ASSERT (FALSE);
>> + }
>> + }
>> +
>> + if (Bounce) {
>> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
>> + Status = EFI_DEVICE_ERROR;
>> + goto FreeMapInfo;
>> + }
>> +
>> + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
>> + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo-
>> >NumberOfBytes),
>> + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
>> + if (EFI_ERROR (Status)) {
>> + goto FreeMapInfo;
>> + }
>> + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
>> + if (Operation == EfiPciIoOperationBusMasterRead) {
>> + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
>> + }
>> + *DeviceAddress = MapInfo->AllocAddress;
>> + } else {
>> + MapInfo->AllocAddress = 0;
>> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
>> +
>> + //
>> + // We are not using a bounce buffer: the mapping is sufficiently
>> + // aligned to allow us to simply flush the caches. Note that cleaning
>> + // the caches is necessary for both data directions:
>> + // - for bus master read, we want the latest data to be present
>> + // in main memory
>> + // - for bus master write, we don't want any stale dirty cachelines that
>> + // may be written back unexpectedly, and clobber the data written to
>> + // main memory by the device.
>> + //
>> + mCpu->FlushDataCache (mCpu,
>> (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
>> + *NumberOfBytes, EfiCpuFlushTypeWriteBack);
>> + }
>> +
>> + *Mapping = MapInfo;
>> + return EFI_SUCCESS;
>> +
>> +FreeMapInfo:
>> + FreePool (MapInfo);
>> +
>> + return Status;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +NonCoherentPciIoUnmap (
>> + IN EFI_PCI_IO_PROTOCOL *This,
>> + IN VOID *Mapping
>> + )
>> +{
>> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
>> +
>> + if (Mapping == NULL) {
>> + return EFI_DEVICE_ERROR;
>> + }
>> +
>> + MapInfo = Mapping;
>> + if (MapInfo->AllocAddress != 0) {
>> + //
>> + // We are using a bounce buffer: copy back the data if necessary,
>> + // and free the buffer.
>> + //
>> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
>> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo-
>> >AllocAddress,
>> + MapInfo->NumberOfBytes);
>> + }
>> + NonCoherentPciIoFreeBuffer (This,
>> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
>> + (VOID *)(UINTN)MapInfo->AllocAddress);
>> + } else {
>> + //
>> + // We are *not* using a bounce buffer: if this is a bus master write,
>> + // we have to invalidate the caches so the CPU will see the uncached
>> + // data written by the device.
>> + //
>> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
>> + mCpu->FlushDataCache (mCpu,
>> + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
>> + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
>> + }
>> + }
>> + FreePool (MapInfo);
>> + return EFI_SUCCESS;
>> +}
>>
>> STATIC
>> EFI_STATUS
>> @@ -726,12 +1046,21 @@ InitializePciIoProtocol (
>> EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
>> INTN Idx;
>>
>> + InitializeListHead (&Dev->UncachedAllocationList);
>> +
>> Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
>> Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
>>
>> // Copy protocol structure
>> CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
>>
>> + if (Dev->Device->DmaType ==
>> NonDiscoverableDeviceDmaTypeNonCoherent) {
>> + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
>> + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
>> + Dev->PciIo.Map = NonCoherentPciIoMap;
>> + Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
>> + }
>> +
>> if (CompareGuid (Dev->Device->Type,
>> &gEdkiiNonDiscoverableAhciDeviceGuid)) {
>> Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
>> Dev->ConfigSpace.Hdr.ClassCode[1] =
>> PCI_CLASS_MASS_STORAGE_SATADPA;
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> index bc0a3d3258f9..449614862911 100644
>> ---
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> @@ -15,6 +15,8 @@
>> #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>> #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>>
>> +#include <PiDxe.h>
>> +
>> #include <Library/BaseMemoryLib.h>
>> #include <Library/DebugLib.h>
>> #include <Library/MemoryAllocationLib.h>
>> @@ -25,6 +27,7 @@
>>
>> #include <Protocol/ComponentName.h>
>> #include <Protocol/NonDiscoverableDevice.h>
>> +#include <Protocol/Cpu.h>
>> #include <Protocol/PciIo.h>
>>
>> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
>> 'D')
>> @@ -38,6 +41,27 @@
>>
>> #define PCI_MAX_BARS 6
>>
>> +extern EFI_CPU_ARCH_PROTOCOL *mCpu;
>> +
>> +typedef struct {
>> + //
>> + // The linked-list next pointer
>> + //
>> + LIST_ENTRY List;
>> + //
>> + // The address of the uncached allocation
>> + //
>> + VOID *HostAddress;
>> + //
>> + // The number of pages in the allocation
>> + //
>> + UINTN NumPages;
>> + //
>> + // The attributes of the allocation
>> + //
>> + UINT64 Attributes;
>> +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
>> +
>> typedef struct {
>> UINT32 Signature;
>> //
>> @@ -71,6 +95,11 @@ typedef struct {
>> // Whether this device has been enabled
>> //
>> BOOLEAN Enabled;
>> + //
>> + // Linked list to keep track of uncached allocations performed
>> + // on behalf of this device
>> + //
>> + LIST_ENTRY UncachedAllocationList;
>> } NON_DISCOVERABLE_PCI_DEVICE;
>>
>> VOID
>> --
>> 2.7.4
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-12-15 8:22 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel
2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
2016-12-14 9:15 ` Ard Biesheuvel
2016-12-15 8:17 ` Ni, Ruiyu
2016-12-15 8:22 ` Ard Biesheuvel
2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox