From: "Jiading Zhang" <jdzhang@kunluntech.com.cn>
To: devel@edk2.groups.io
Subject: [PATCH] MdeModulePkg/XhciDxe: Allocate the Ring segments at 64K aligned address to avoid the Rings crossing a 64K byte boundary.
Date: Mon, 10 Oct 2022 19:21:11 -0700 [thread overview]
Message-ID: <UDjx.1665454871838858271.aIbe@groups.io> (raw)
[-- Attachment #1: Type: text/plain, Size: 15326 bytes --]
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
[-- Attachment #2: Type: text/html, Size: 24067 bytes --]
reply other threads:[~2022-10-11 2:21 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=UDjx.1665454871838858271.aIbe@groups.io \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox