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 --- 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