According the Xhci Spec, TRB Rings may be larger than a Page, however they shall not cross a 64K byte boundary, so allocate the rings at 64K aligned address to avoid they crossing a 64K byte boundary.
 
Signed-off-by: jdzhang <jdzhang@kunluntech.com.cn>
---
 MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 112 +++++++++++------------
 MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h |   4 +
 2 files changed, 56 insertions(+), 60 deletions(-)
 
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index 4ae0297607..b020bb064b 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -473,7 +473,6 @@ XhcInitSched (
 {
   VOID                  *Dcbaa;
   EFI_PHYSICAL_ADDRESS  DcbaaPhy;
-  UINT64                CmdRing;
   EFI_PHYSICAL_ADDRESS  CmdRingPhy;
   UINTN                 Entries;
   UINT32                MaxScratchpadBufs;
@@ -602,8 +601,7 @@ XhcInitSched (
   // Transfer Ring it checks for a Cycle bit transition. If a transition detected, the ring is empty.
   // So we set RCS as inverted PCS init value to let Command Ring empty
   //
-  CmdRing    = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0;
-  CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN)CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);
+  CmdRingPhy = (UINT64)(UINTN)Xhc->CmdRing.RingPhy;
   ASSERT ((CmdRingPhy & 0x3F) == 0);
   CmdRingPhy |= XHC_CRCR_RCS;
   //
@@ -790,23 +788,28 @@ CreateEventRing (
   EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;
   UINTN                       Size;
   EFI_PHYSICAL_ADDRESS        ERSTPhy;
-  EFI_PHYSICAL_ADDRESS        DequeuePhy;
+  EFI_STATUS                  Status;
 
   ASSERT (EventRing != NULL);
-
+  
+  //To meet the 64KB Boundary Requirement in xhci spec chapter 6  Table 6-1, allocate the Ring segments at 64K aligned address.
   Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;
-  Buf  = UsbHcAllocateMem (Xhc->MemPool, Size);
-  ASSERT (Buf != NULL);
-  ASSERT (((UINTN)Buf & 0x3F) == 0);
-  ZeroMem (Buf, Size);
+  Status = UsbHcAllocateAlignedPages (
+           Xhc->PciIo,
+           EFI_SIZE_TO_PAGES (Size),
+           SIZE_64KB,
+           (VOID **) &(EventRing->EventRingSeg0),
+           &(EventRing->EventRingPhy),
+           &(EventRing->EventRingMap)
+           );
+  ASSERT_EFI_ERROR (Status);
+  
+  ZeroMem (EventRing->EventRingSeg0, Size);
 
-  EventRing->EventRingSeg0    = Buf;
   EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;
   EventRing->EventRingDequeue = (TRB_TEMPLATE *)EventRing->EventRingSeg0;
   EventRing->EventRingEnqueue = (TRB_TEMPLATE *)EventRing->EventRingSeg0;
 
-  DequeuePhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, Size);
-
   //
   // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
   // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
@@ -821,8 +824,8 @@ CreateEventRing (
 
   ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *)Buf;
   EventRing->ERSTBase   = ERSTBase;
-  ERSTBase->PtrLo       = XHC_LOW_32BIT (DequeuePhy);
-  ERSTBase->PtrHi       = XHC_HIGH_32BIT (DequeuePhy);
+  ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingPhy);
+  ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingPhy);
   ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
 
   ERSTPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, ERSTBase, Size);
@@ -844,12 +847,12 @@ CreateEventRing (
   XhcWriteRuntimeReg (
     Xhc,
     XHC_ERDP_OFFSET,
-    XHC_LOW_32BIT ((UINT64)(UINTN)DequeuePhy)
+    XHC_LOW_32BIT ((UINT64)(UINTN)EventRing->EventRingPhy)
     );
   XhcWriteRuntimeReg (
     Xhc,
     XHC_ERDP_OFFSET + 4,
-    XHC_HIGH_32BIT ((UINT64)(UINTN)DequeuePhy)
+    XHC_HIGH_32BIT ((UINT64)(UINTN)EventRing->EventRingPhy)
     );
   //
   // Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2)
@@ -888,16 +891,24 @@ CreateTransferRing (
   OUT TRANSFER_RING      *TransferRing
   )
 {
-  VOID                  *Buf;
+  UINTN                 Size;
   LINK_TRB              *EndTrb;
-  EFI_PHYSICAL_ADDRESS  PhyAddr;
-
-  Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);
-  ASSERT (Buf != NULL);
-  ASSERT (((UINTN)Buf & 0x3F) == 0);
-  ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
+  EFI_STATUS            Status;
+  
+  //To meet the 64KB Boundary Requirement in xhci spec chapter 6  Table 6-1, allocate the Ring segments at 64K aligned address.
+  Size = sizeof (TRB_TEMPLATE) * TrbNum;
+  Status = UsbHcAllocateAlignedPages (
+           Xhc->PciIo,
+           EFI_SIZE_TO_PAGES (Size),
+           SIZE_64KB,
+           (VOID **) &(TransferRing->RingSeg0),
+           &(TransferRing->RingPhy),
+           &(TransferRing->RingMap)
+           );
+  ASSERT_EFI_ERROR (Status);
+      
+  ZeroMem (TransferRing->RingSeg0, Size);
 
-  TransferRing->RingSeg0    = Buf;
   TransferRing->TrbNumber   = TrbNum;
   TransferRing->RingEnqueue = (TRB_TEMPLATE *)TransferRing->RingSeg0;
   TransferRing->RingDequeue = (TRB_TEMPLATE *)TransferRing->RingSeg0;
@@ -907,11 +918,10 @@ CreateTransferRing (
   // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
   // point to the first TRB in the ring.
   //
-  EndTrb        = (LINK_TRB *)((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
+  EndTrb        = (LINK_TRB *)((UINTN)TransferRing->RingSeg0 + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
   EndTrb->Type  = TRB_TYPE_LINK;
-  PhyAddr       = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum);
-  EndTrb->PtrLo = XHC_LOW_32BIT (PhyAddr);
-  EndTrb->PtrHi = XHC_HIGH_32BIT (PhyAddr);
+  EndTrb->PtrLo = XHC_LOW_32BIT (TransferRing->RingPhy);
+  EndTrb->PtrHi = XHC_HIGH_32BIT (TransferRing->RingPhy);
   //
   // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
   //
@@ -943,7 +953,7 @@ XhcFreeEventRing (
   //
   // Free EventRing Segment 0
   //
-  UsbHcFreeMem (Xhc->MemPool, EventRing->EventRingSeg0, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
+  UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)EventRing->EventRingSeg0, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER), (VOID *)EventRing->EventRingMap);
 
   //
   // Free ESRT table
@@ -984,7 +994,7 @@ XhcFreeSched (
   }
 
   if (Xhc->CmdRing.RingSeg0 != NULL) {
-    UsbHcFreeMem (Xhc->MemPool, Xhc->CmdRing.RingSeg0, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);
+    UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)Xhc->CmdRing.RingSeg0, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER), (VOID *)Xhc->CmdRing.RingMap);
     Xhc->CmdRing.RingSeg0 = NULL;
   }
 
@@ -1041,8 +1051,7 @@ IsTransferRingTrb (
     if (CheckedTrb->Type == TRB_TYPE_LINK) {
       LinkTrb    = (LINK_TRB *)CheckedTrb;
       PhyAddr    = (EFI_PHYSICAL_ADDRESS)(LinkTrb->PtrLo | LShiftU64 ((UINT64)LinkTrb->PtrHi, 32));
-      CheckedTrb = (TRB_TEMPLATE *)(UINTN)UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN)PhyAddr, sizeof (TRB_TEMPLATE));
-      ASSERT (CheckedTrb == Urb->Ring->RingSeg0);
+      ASSERT (PhyAddr == Urb->Ring->RingPhy);
     }
   }
 
@@ -1150,8 +1159,7 @@ XhcCheckUrbResult (
     // Need convert pci device address to host address
     //
     PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64)EvtTrb->TRBPtrHi, 32));
-    TRBPtr  = (TRB_TEMPLATE *)(UINTN)UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN)PhyAddr, sizeof (TRB_TEMPLATE));
-
+    TRBPtr  = (TRB_TEMPLATE *)((UINTN)(VOID*)Xhc->EventRing.EventRingSeg0 + (UINTN)(PhyAddr - Xhc->EventRing.EventRingPhy));
     //
     // Update the status of URB including the pending URB, the URB that is currently checked,
     // and URBs in the XHCI's async interrupt transfer list.
@@ -1255,7 +1263,7 @@ EXIT:
   High       = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);
   XhcDequeue = (UINT64)(LShiftU64 ((UINT64)High, 32) | Low);
 
-  PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->EventRing.EventRingDequeue, sizeof (TRB_TEMPLATE));
+  PhyAddr = Xhc->EventRing.EventRingPhy + (UINT64)((UINTN)(VOID *)(Xhc->EventRing.EventRingDequeue) - (UINTN)(Xhc->EventRing.EventRingSeg0));
 
   if ((XhcDequeue & (~0x0F)) != (PhyAddr & (~0x0F))) {
     //
@@ -2273,11 +2281,7 @@ XhcInitializeDeviceSlot (
   //
   // Init the DCS(dequeue cycle state) as the transfer ring's CCS
   //
-  PhyAddr = UsbHcGetPciAddrForHostAddr (
-              Xhc->MemPool,
-              ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,
-              sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
-              );
+  PhyAddr = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingPhy;
   InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;
   InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);
 
@@ -2489,11 +2493,7 @@ XhcInitializeDeviceSlot64 (
   //
   // Init the DCS(dequeue cycle state) as the transfer ring's CCS
   //
-  PhyAddr = UsbHcGetPciAddrForHostAddr (
-              Xhc->MemPool,
-              ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,
-              sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
-              );
+  PhyAddr = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingPhy;
   InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;
   InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);
 
@@ -2623,7 +2623,7 @@ XhcDisableSlotCmd (
     if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {
       RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;
       if (RingSeg != NULL) {
-        UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
+        UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER), ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingMap);
       }
 
       FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);
@@ -2734,7 +2734,7 @@ XhcDisableSlotCmd64 (
     if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {
       RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;
       if (RingSeg != NULL) {
-        UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
+        UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER),((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingMap);
       }
 
       FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);
@@ -2954,11 +2954,7 @@ XhcInitializeEndpointContext (
         continue;
     }
 
-    PhyAddr = UsbHcGetPciAddrForHostAddr (
-                Xhc->MemPool,
-                ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
-                sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
-                );
+    PhyAddr = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPhy;
     PhyAddr                      &= ~((EFI_PHYSICAL_ADDRESS)0x0F);
     PhyAddr                      |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
     InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
@@ -3153,11 +3149,7 @@ XhcInitializeEndpointContext64 (
         continue;
     }
 
-    PhyAddr = UsbHcGetPciAddrForHostAddr (
-                Xhc->MemPool,
-                ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
-                sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
-                );
+    PhyAddr = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPhy;
     PhyAddr                      &= ~((EFI_PHYSICAL_ADDRESS)0x0F);
     PhyAddr                      |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
     InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
@@ -3503,7 +3495,7 @@ XhcSetTrDequeuePointer (
   // Send stop endpoint command to transit Endpoint from running to stop state
   //
   ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
-  PhyAddr              = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
+  PhyAddr              = Urb->Ring->RingPhy + (UINT64)((UINTN)(VOID *)(Xhc->EventRing.EventRingEnqueue) - (UINTN)(Xhc->EventRing.EventRingSeg0));
   CmdSetTRDeq.PtrLo    = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;
   CmdSetTRDeq.PtrHi    = XHC_HIGH_32BIT (PhyAddr);
   CmdSetTRDeq.CycleBit = 1;
@@ -3661,7 +3653,7 @@ XhcSetInterface (
       if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {
         RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;
         if (RingSeg != NULL) {
-          UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
+          UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER), ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingMap);
         }
 
         FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);
@@ -3867,7 +3859,7 @@ XhcSetInterface64 (
       if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {
         RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;
         if (RingSeg != NULL) {
-          UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
+          UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER), ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingMap);
         }
 
         FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
index 7c85f7993b..e9792b5941 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
@@ -144,6 +144,8 @@ typedef struct _TRANSFER_RING {
   TRB_TEMPLATE    *RingEnqueue;
   TRB_TEMPLATE    *RingDequeue;
   UINT32          RingPCS;
+  EFI_PHYSICAL_ADDRESS  RingPhy;
+  VOID            *RingMap;
 } TRANSFER_RING;
 
 typedef struct _EVENT_RING {
@@ -153,6 +155,8 @@ typedef struct _EVENT_RING {
   TRB_TEMPLATE    *EventRingEnqueue;
   TRB_TEMPLATE    *EventRingDequeue;
   UINT32          EventRingCCS;
+  EFI_PHYSICAL_ADDRESS  EventRingPhy;
+  VOID            *EventRingMap;
 } EVENT_RING;
 
 //
-- 
2.20.1.windows.1