summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c')
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
index 99fb3521d5..d0ad1582e4 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
@@ -132,8 +132,9 @@ UsbHcFreeMemBlock (
/**
Alloc some memory from the block.
- @param Block The memory block to allocate memory from.
- @param Units Number of memory units to allocate.
+ @param Block The memory block to allocate memory from.
+ @param Units Number of memory units to allocate.
+ @param AllocationForRing The allocated memory is for Ring or not.
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
the return value is NULL.
@@ -142,7 +143,8 @@ UsbHcFreeMemBlock (
VOID *
UsbHcAllocMemFromBlock (
IN USBHC_MEM_BLOCK *Block,
- IN UINTN Units
+ IN UINTN Units,
+ IN BOOLEAN AllocationForRing
)
{
UINTN Byte;
@@ -151,12 +153,15 @@ UsbHcAllocMemFromBlock (
UINT8 StartBit;
UINTN Available;
UINTN Count;
+ UINTN MemUnitAddr;
+ UINTN AlignmentMask;
ASSERT ((Block != 0) && (Units != 0));
- StartByte = 0;
- StartBit = 0;
- Available = 0;
+ StartByte = 0;
+ StartBit = 0;
+ Available = 0;
+ AlignmentMask = ~((UINTN)USBHC_MEM_TRB_RINGS_BOUNDARY - 1);
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
//
@@ -165,6 +170,20 @@ UsbHcAllocMemFromBlock (
// Available counts the consective number of zero bit.
//
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
+ if (AllocationForRing && (Available != 0)) {
+ MemUnitAddr = (UINTN)Block->BufHost + (Byte * 8 + Bit) * USBHC_MEM_UNIT;
+ if ((MemUnitAddr & AlignmentMask) != ((MemUnitAddr - USBHC_MEM_UNIT) & AlignmentMask)) {
+ //
+ // If the TRB Ring memory cross 64K-byte boundary, then restart the
+ // search starting at current memory unit.
+ // Doing so is to meet the TRB Ring boundary requirement in XHCI spec.
+ //
+ Available = 0;
+ StartByte = Byte;
+ StartBit = Bit;
+ }
+ }
+
Available++;
if (Available >= Units) {
@@ -438,8 +457,9 @@ UsbHcFreeMemPool (
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
- @param Pool The host controller's memory pool.
- @param Size Size of the memory to allocate.
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+ @param AllocationForRing The allocated memory is for Ring or not.
@return The allocated memory or NULL.
@@ -447,7 +467,8 @@ UsbHcFreeMemPool (
VOID *
UsbHcAllocateMem (
IN USBHC_MEM_POOL *Pool,
- IN UINTN Size
+ IN UINTN Size,
+ IN BOOLEAN AllocationForRing
)
{
USBHC_MEM_BLOCK *Head;
@@ -466,7 +487,7 @@ UsbHcAllocateMem (
// First check whether current memory blocks can satisfy the allocation.
//
for (Block = Head; Block != NULL; Block = Block->Next) {
- Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT, AllocationForRing);
if (Mem != NULL) {
ZeroMem (Mem, Size);
@@ -501,7 +522,7 @@ UsbHcAllocateMem (
// Add the new memory block to the pool, then allocate memory from it
//
UsbHcInsertMemBlockToPool (Head, NewBlock);
- Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT, AllocationForRing);
if (Mem != NULL) {
ZeroMem (Mem, Size);