VirtualBox

Changeset 45666 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 22, 2013 2:49:34 PM (12 years ago)
Author:
vboxsync
Message:

OHCI: Periodically cancel orphaned URBs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/DevOHCI.cpp

    r45025 r45666  
    303303    {
    304304        /** Address of the transport descriptor. */
    305         uint32_t GCPhysTD;
    306 #if HC_ARCH_BITS == 64
    307         uint32_t Alignment0; /**< Alignment pUrb correctly. */
    308 #endif
     305        uint32_t    GCPhysTD;
     306        /** Flag indicating an inactive (not-linked) URB. */
     307        bool        fInactive;
    309308        /** Pointer to the URB. */
    310309        R3PTRTYPE(PVUSBURB) pUrb;
     
    34463445                break;
    34473446        }
    3448 
     3447        else
     3448        {
     3449            if (Ed.hwinfo & ED_HWINFO_SKIP)
     3450            {
     3451                LogFlow(("ohciServicePeriodicList: Ed=%#010RX32 Ed.TailP=%#010RX32 SKIP\n", EdAddr, Ed.TailP));
     3452                /* If the ED is in 'skip' state, no transactions on it are allowed and we must
     3453                 * cancel outstanding URBs, if any.
     3454                 */
     3455                uint32_t TdAddr = Ed.HeadP & ED_PTR_MASK;
     3456                PVUSBURB pUrb = ohciTdInFlightUrb(pThis, TdAddr);
     3457                if (pUrb)
     3458                    pThis->RootHub.pIRhConn->pfnCancelUrbsEp(pThis->RootHub.pIRhConn, pUrb);
     3459            }
     3460        }
    34493461        /* next end point */
    34503462        EdAddr = Ed.NextED & ED_PTR_MASK;
     
    35223534}
    35233535
     3536/**
     3537 * Go over the in-flight URB list and cancel any URBs that are no longer in use.
     3538 * This occurs when the host removes EDs or TDs from the lists and we don't notice
     3539 * the sKip bit. Such URBs must be promptly canceled, otherwise there is a risk
     3540 * they might "steal" data destined for another URB.
     3541 */
     3542static void ohciCancelOrphanedURBs(POHCI pThis)
     3543{
     3544    bool fValidHCCA = !(    pThis->hcca >= OHCI_HCCA_MASK
     3545                        ||  pThis->hcca < ~OHCI_HCCA_MASK);
     3546    unsigned    i, cLeft;
     3547    int         j;
     3548    uint32_t    EdAddr;
     3549    PVUSBURB    pUrb;
     3550
     3551    /* If the HCCA is not currently valid, there's nothing to do. */
     3552    if (!fValidHCCA)
     3553        return;
     3554
     3555    /* Initially mark all in-flight URBs as inactive. */
     3556    for (i = 0, cLeft = pThis->cInFlight; cLeft && i < RT_ELEMENTS(pThis->aInFlight); i++)
     3557    {
     3558        if (pThis->aInFlight[i].pUrb)
     3559        {
     3560            pThis->aInFlight[i].fInactive = true;
     3561            cLeft--;
     3562        }
     3563    }
     3564    Assert(cLeft == 0);
     3565
     3566    /* Go over all bulk/control/interrupt endpoint lists; any URB found in these lists
     3567     * is marked as active again.
     3568     */
     3569    for (i = 0; i < OHCI_HCCA_NUM_INTR + 2; i++)
     3570    {
     3571        switch (i)
     3572        {
     3573        case OHCI_HCCA_NUM_INTR:
     3574            EdAddr = pThis->bulk_head;
     3575            break;
     3576        case OHCI_HCCA_NUM_INTR + 1:
     3577            EdAddr = pThis->ctrl_head;
     3578            break;
     3579        default:
     3580            ohciGetDWords(pThis, pThis->hcca + i * sizeof(EdAddr), &EdAddr, 1);
     3581            break;
     3582        }
     3583        while (EdAddr)
     3584        {
     3585            OHCIED Ed;
     3586            OHCITD Td;
     3587            ohciReadEd(pThis, EdAddr, &Ed);
     3588            uint32_t TdAddr = Ed.HeadP & ED_PTR_MASK;
     3589            unsigned k = 0;
     3590            do
     3591            {
     3592                ohciReadTd(pThis, TdAddr, &Td);
     3593                j = ohci_in_flight_find(pThis, TdAddr);
     3594                if (j > -1)
     3595                    pThis->aInFlight[j].fInactive = false;
     3596                TdAddr = Td.NextTD & ED_PTR_MASK;
     3597                /* Failsafe for temporarily looped lists. */
     3598                if (++k == 128)
     3599                    break;
     3600            } while (TdAddr != (Ed.TailP & ED_PTR_MASK));
     3601            EdAddr = Ed.NextED & ED_PTR_MASK;
     3602        }
     3603    }
     3604
     3605    /* In-flight URBs still marked as inactive are not used anymore and need
     3606     * to be canceled.
     3607     */
     3608    for (i = 0, cLeft = pThis->cInFlight; cLeft && i < RT_ELEMENTS(pThis->aInFlight); i++)
     3609    {
     3610        if (pThis->aInFlight[i].pUrb)
     3611        {
     3612            cLeft--;
     3613            pUrb = pThis->aInFlight[i].pUrb;
     3614            if (pThis->aInFlight[i].fInactive
     3615                && pUrb->enmState == VUSBURBSTATE_IN_FLIGHT
     3616                && !pUrb->enmType == VUSBXFERTYPE_CTRL)
     3617                pThis->RootHub.pIRhConn->pfnCancelUrbsEp(pThis->RootHub.pIRhConn, pUrb);
     3618        }
     3619    }
     3620    Assert(cLeft == 0);
     3621}
    35243622
    35253623/**
     
    37003798    if ( (pThis->dqic != 0x7) && (pThis->dqic != 0) )
    37013799        pThis->dqic--;
     3800
     3801    /* Clean up any URBs that have been removed */
     3802    ohciCancelOrphanedURBs(pThis);
    37023803
    37033804    /* Start the next frame */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette