X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FXhciDxe%2FXhciSched.c;h=f7f3409686b8c9d13484b0f2cbb571475b63809b;hp=58a2f984a9450a127e065f95fa8ec35580ef15c7;hb=396ae94d46906c52875054a0487d37cad2ff1216;hpb=3719c2aa879bcbcf3f0ab1f710e81fe2dbc19d9a diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c index 58a2f984a9..f7f3409686 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c @@ -604,8 +604,6 @@ XhcInitSched ( XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRingPhy)); XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRingPhy)); - DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0)); - // // Disable the 'interrupter enable' bit in USB_CMD // and clear IE & IP bit in all Interrupter X Management Registers. @@ -620,7 +618,10 @@ XhcInitSched ( // Allocate EventRing for Cmd, Ctrl, Bulk, Interrupt, AsynInterrupt transfer // CreateEventRing (Xhc, &Xhc->EventRing); - DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_EVENTRING=0x%x\n", Xhc->EventRing.EventRingSeg0)); + DEBUG ((DEBUG_INFO, "XhcInitSched: Created CMD ring [%p~%p) EVENT ring [%p~%p)\n", + Xhc->CmdRing.RingSeg0, (UINTN)Xhc->CmdRing.RingSeg0 + sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER, + Xhc->EventRing.EventRingSeg0, (UINTN)Xhc->EventRing.EventRingSeg0 + sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER + )); } /** @@ -977,45 +978,42 @@ XhcFreeSched ( } /** - Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list. + Check if the Trb is a transaction of the URB. - @param Xhc The XHCI Instance. - @param Trb The TRB to be checked. - @param Urb The pointer to the matched Urb. + @param Trb The TRB to be checked + @param Urb The URB to be checked. - @retval TRUE The Trb is matched with a transaction of the URBs in the async list. - @retval FALSE The Trb is not matched with any URBs in the async list. + @retval TRUE It is a transaction of the URB. + @retval FALSE It is not any transaction of the URB. **/ BOOLEAN -IsAsyncIntTrb ( +IsTransferRingTrb ( IN USB_XHCI_INSTANCE *Xhc, IN TRB_TEMPLATE *Trb, - OUT URB **Urb + IN URB *Urb ) { - LIST_ENTRY *Entry; - LIST_ENTRY *Next; - TRB_TEMPLATE *CheckedTrb; - URB *CheckedUrb; - UINTN Index; + LINK_TRB *LinkTrb; + TRB_TEMPLATE *CheckedTrb; + UINTN Index; + EFI_PHYSICAL_ADDRESS PhyAddr; - EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { - CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList); - CheckedTrb = CheckedUrb->TrbStart; - for (Index = 0; Index < CheckedUrb->TrbNum; Index++) { - if (Trb == CheckedTrb) { - *Urb = CheckedUrb; - return TRUE; - } - CheckedTrb++; - // - // If the checked TRB is the link TRB at the end of the transfer ring, - // recircle it to the head of the ring. - // - if (CheckedTrb->Type == TRB_TYPE_LINK) { - CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0; - } + CheckedTrb = Urb->TrbStart; + for (Index = 0; Index < Urb->TrbNum; Index++) { + if (Trb == CheckedTrb) { + return TRUE; + } + CheckedTrb++; + // + // If the checked TRB is the link TRB at the end of the transfer ring, + // recircle it to the head of the ring. + // + 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); } } @@ -1023,38 +1021,39 @@ IsAsyncIntTrb ( } /** - Check if the Trb is a transaction of the URB. + Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list. - @param Trb The TRB to be checked - @param Urb The transfer ring to be checked. + @param Xhc The XHCI Instance. + @param Trb The TRB to be checked. + @param Urb The pointer to the matched Urb. - @retval TRUE It is a transaction of the URB. - @retval FALSE It is not any transaction of the URB. + @retval TRUE The Trb is matched with a transaction of the URBs in the async list. + @retval FALSE The Trb is not matched with any URBs in the async list. **/ BOOLEAN -IsTransferRingTrb ( +IsAsyncIntTrb ( + IN USB_XHCI_INSTANCE *Xhc, IN TRB_TEMPLATE *Trb, - IN URB *Urb + OUT URB **Urb ) { - TRB_TEMPLATE *CheckedTrb; - UINTN Index; - - CheckedTrb = Urb->Ring->RingSeg0; - - ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER); + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + URB *CheckedUrb; - for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) { - if (Trb == CheckedTrb) { + EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { + CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList); + if (IsTransferRingTrb (Xhc, Trb, CheckedUrb)) { + *Urb = CheckedUrb; return TRUE; } - CheckedTrb++; } return FALSE; } + /** Check the URB's execution result and update the URB's result accordingly. @@ -1131,7 +1130,7 @@ XhcCheckUrbResult ( // This way is used to avoid that those completed async transfer events don't get // handled in time and are flushed by newer coming events. // - if (IsTransferRingTrb (TRBPtr, Urb)) { + if (IsTransferRingTrb (Xhc, TRBPtr, Urb)) { CheckedUrb = Urb; } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) { CheckedUrb = AsyncUrb; @@ -1319,6 +1318,7 @@ XhciDelAsyncIntTransfer ( LIST_ENTRY *Next; URB *Urb; EFI_USB_DATA_DIRECTION Direction; + EFI_STATUS Status; Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut; EpNum &= 0x0F; @@ -1330,6 +1330,15 @@ XhciDelAsyncIntTransfer ( if ((Urb->Ep.BusAddr == BusAddr) && (Urb->Ep.EpAddr == EpNum) && (Urb->Ep.Direction == Direction)) { + // + // Device doesn't finish the IntTransfer until real data comes + // So the TRB should be removed as well. + // + Status = XhcDequeueTrbFromEndpoint (Xhc, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "XhciDelAsyncIntTransfer: XhcDequeueTrbFromEndpoint failed\n")); + } + RemoveEntryList (&Urb->UrbList); FreePool (Urb->Data); XhcFreeUrb (Xhc, Urb); @@ -1354,9 +1363,20 @@ XhciDelAllAsyncIntTransfers ( LIST_ENTRY *Entry; LIST_ENTRY *Next; URB *Urb; + EFI_STATUS Status; EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList); + + // + // Device doesn't finish the IntTransfer until real data comes + // So the TRB should be removed as well. + // + Status = XhcDequeueTrbFromEndpoint (Xhc, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "XhciDelAllAsyncIntTransfers: XhcDequeueTrbFromEndpoint failed\n")); + } + RemoveEntryList (&Urb->UrbList); FreePool (Urb->Data); XhcFreeUrb (Xhc, Urb); @@ -2649,6 +2669,11 @@ XhcInitializeEndpointContext ( EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG ((DEBUG_INFO, "Endpoint[%x]: Created BULK ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break; @@ -2717,6 +2742,11 @@ XhcInitializeEndpointContext ( EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG ((DEBUG_INFO, "Endpoint[%x]: Created INT ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break; @@ -2831,6 +2861,11 @@ XhcInitializeEndpointContext64 ( EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG ((DEBUG_INFO, "Endpoint64[%x]: Created BULK ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break; @@ -2899,6 +2934,11 @@ XhcInitializeEndpointContext64 ( EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG ((DEBUG_INFO, "Endpoint64[%x]: Created INT ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN) EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break;