summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brasen via groups.io <jbrasen=nvidia.com@groups.io>2022-02-14 18:45:31 +0000
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-10-01 10:44:30 +0000
commit6a2b20ff97e4256970644a07f74a4c5655bf5072 (patch)
tree5782f75df27aaf93ef4bebae9feea48bd9a95767
parent7aa06237b856fd6f8187cc1715a3fe08ab4e98ed (diff)
downloadedk2-6a2b20ff97e4256970644a07f74a4c5655bf5072.tar.gz
edk2-6a2b20ff97e4256970644a07f74a4c5655bf5072.tar.bz2
edk2-6a2b20ff97e4256970644a07f74a4c5655bf5072.zip
MdeModulePkg/NonDiscoverablePciDeviceDxe: Allow partial FreeBuffer
Add support for partial free of non cached buffers. If a request for less than the full size is requested new allocations for the remaining head and tail of the buffer are added to the list. Added verification that Buffer is EFI_PAGE_SIZE aligned. The XHCI driver does this if the page size for the controller is >4KB. Signed-off-by: Jeff Brasen <jbrasen@nvidia.com> Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
-rw-r--r--MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index c1c5c6267c..2fb78d8f96 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -960,13 +960,25 @@ NonCoherentPciIoFreeBuffer (
LIST_ENTRY *Entry;
EFI_STATUS Status;
NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocHead;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocTail;
BOOLEAN Found;
+ UINTN StartPages;
+ UINTN EndPages;
+
+ if (HostAddress != ALIGN_POINTER (HostAddress, EFI_PAGE_SIZE)) {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ return EFI_INVALID_PARAMETER;
+ }
Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This);
Found = FALSE;
Alloc = NULL;
+ AllocHead = NULL;
+ AllocTail = NULL;
+
//
// Find the uncached allocation list entry associated
// with this allocation
@@ -976,9 +988,19 @@ NonCoherentPciIoFreeBuffer (
Entry = Entry->ForwardLink)
{
Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
- if ((Alloc->HostAddress == HostAddress) && (Alloc->NumPages == Pages)) {
+
+ StartPages = 0;
+ if (Alloc->HostAddress < HostAddress) {
+ StartPages = EFI_SIZE_TO_PAGES (
+ (UINTN)HostAddress - (UINTN)Alloc->HostAddress
+ );
+ }
+
+ if ((Alloc->HostAddress <= HostAddress) &&
+ (Alloc->NumPages >= (Pages + StartPages)))
+ {
//
- // We are freeing the exact allocation we were given
+ // We are freeing at least part of what we were given
// before by AllocateBuffer()
//
Found = TRUE;
@@ -991,7 +1013,45 @@ NonCoherentPciIoFreeBuffer (
return EFI_NOT_FOUND;
}
+ EndPages = Alloc->NumPages - (Pages + StartPages);
+
+ if (StartPages != 0) {
+ AllocHead = AllocatePool (sizeof *AllocHead);
+ if (AllocHead == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AllocHead->HostAddress = Alloc->HostAddress;
+
+ AllocHead->NumPages = StartPages;
+ AllocHead->Attributes = Alloc->Attributes;
+ }
+
+ if (EndPages != 0) {
+ AllocTail = AllocatePool (sizeof *AllocTail);
+ if (AllocTail == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AllocTail->HostAddress = (UINT8 *)Alloc->HostAddress +
+ EFI_PAGES_TO_SIZE (Pages + StartPages);
+
+ AllocTail->NumPages = EndPages;
+ AllocTail->Attributes = Alloc->Attributes;
+ }
+
RemoveEntryList (&Alloc->List);
+ //
+ // Record this new sub allocations in the linked list, so we
+ // can restore the memory space attributes later
+ //
+ if (AllocHead != NULL) {
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocHead->List);
+ }
+
+ if (AllocTail != NULL) {
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocTail->List);
+ }
Status = gDS->SetMemorySpaceAttributes (
(EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,