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); diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h index 48ae86141c..c85b0b919f 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h +++ b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h @@ -48,6 +48,8 @@ typedef struct _USBHC_MEM_POOL { #define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK)) +#define USBHC_MEM_TRB_RINGS_BOUNDARY SIZE_64KB + // // Advance the byte and bit to the next bit, adjust byte accordingly. // @@ -92,8 +94,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. @@ -101,7 +104,8 @@ UsbHcFreeMemPool ( VOID * UsbHcAllocateMem ( IN USBHC_MEM_POOL *Pool, - IN UINTN Size + IN UINTN Size, + IN BOOLEAN AllocationForRing ); /** diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c index 4ae0297607..13b0400e83 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c @@ -506,7 +506,7 @@ XhcInitSched ( // Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'. // Entries = (Xhc->MaxSlotsEn + 1) * sizeof (UINT64); - Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries); + Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries, FALSE); ASSERT (Dcbaa != NULL); ZeroMem (Dcbaa, Entries); @@ -795,7 +795,7 @@ CreateEventRing ( ASSERT (EventRing != NULL); Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER; - Buf = UsbHcAllocateMem (Xhc->MemPool, Size); + Buf = UsbHcAllocateMem (Xhc->MemPool, Size, TRUE); ASSERT (Buf != NULL); ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, Size); @@ -814,7 +814,7 @@ CreateEventRing ( EventRing->EventRingCCS = 1; Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER; - Buf = UsbHcAllocateMem (Xhc->MemPool, Size); + Buf = UsbHcAllocateMem (Xhc->MemPool, Size, FALSE); ASSERT (Buf != NULL); ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, Size); @@ -892,7 +892,7 @@ CreateTransferRing ( LINK_TRB *EndTrb; EFI_PHYSICAL_ADDRESS PhyAddr; - Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum); + Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum, TRUE); ASSERT (Buf != NULL); ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum); @@ -2182,7 +2182,7 @@ XhcInitializeDeviceSlot ( // 4.3.3 Device Slot Initialization // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'. // - InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT)); + InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT), FALSE); ASSERT (InputContext != NULL); ASSERT (((UINTN)InputContext & 0x3F) == 0); ZeroMem (InputContext, sizeof (INPUT_CONTEXT)); @@ -2284,7 +2284,7 @@ XhcInitializeDeviceSlot ( // // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'. // - OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT)); + OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT), FALSE); ASSERT (OutputContext != NULL); ASSERT (((UINTN)OutputContext & 0x3F) == 0); ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT)); @@ -2398,7 +2398,7 @@ XhcInitializeDeviceSlot64 ( // 4.3.3 Device Slot Initialization // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'. // - InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64)); + InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64), FALSE); ASSERT (InputContext != NULL); ASSERT (((UINTN)InputContext & 0x3F) == 0); ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64)); @@ -2500,7 +2500,7 @@ XhcInitializeDeviceSlot64 ( // // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'. // - OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64)); + OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64), FALSE); ASSERT (OutputContext != NULL); ASSERT (((UINTN)OutputContext & 0x3F) == 0); ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));