VirtualBox

Changeset 24749 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 18, 2009 12:32:14 AM (15 years ago)
Author:
vboxsync
Message:

DevAHCI: async suspend, reset and power off handling for the SATA part.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r24588 r24749  
    583583    PDMCRITSECT                     lock;
    584584
    585     /** Semaphore that gets set when fSignalIdle is set. */
    586     RTSEMEVENT                      hEvtIdle;
    587 #if HC_ARCH_BITS == 32
    588     uint32_t                        Alignment7;
    589 #endif
    590 
    591585    /** Bitmask of ports which asserted an interrupt. */
    592586    uint32_t                        u32PortsInterrupted;
     
    601595    /** If the new async interface is used if available. */
    602596    bool                            fUseAsyncInterfaceIfAvailable;
    603     /** Indicates that hEvtIdle should be signalled when a port is entering the
    604      * idle state. */
     597    /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
     598     * a port is entering the idle state. */
    605599    bool volatile                   fSignalIdle;
    606600    bool                            afAlignment8[1];
     
    49284922
    49294923    if (pAhciPort->uActTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
    4930         RTSemEventSignal(pAhciPort->pAhciR3->hEvtIdle);
     4924        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    49314925    return rc;
    49324926}
     
    53875381        ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true);
    53885382        if (pAhci->fSignalIdle)
    5389             RTSemEventSignal(pAhci->hEvtIdle);
     5383            PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    53905384
    53915385        rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000);
     
    56525646
    56535647    if (pAhci->fSignalIdle)
    5654         RTSemEventSignal(pAhci->hEvtIdle);
     5648        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    56555649
    56565650    /* Free task state memory */
     
    57855779            ataControllerDestroy(&pAhci->aCts[i]);
    57865780
    5787         RTSemEventDestroy(pAhci->hEvtIdle);
    5788         pAhci->hEvtIdle = NIL_RTSEMEVENT;
    5789 
    57905781        PDMR3CritSectDelete(&pAhci->lock);
    57915782    }
     
    58955886}
    58965887
    5897 static bool ahciWaitForAllAsyncIOIsFinished(PPDMDEVINS pDevIns, unsigned cMillies)
    5898 {
    5899     PAHCI     pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    5900     uint64_t  u64Start;
    5901     PAHCIPort pAhciPort;
    5902     bool      fAllFinished;
    5903 
    5904     ASMAtomicWriteBool(&pAhci->fSignalIdle, true);
    5905     u64Start = RTTimeMilliTS();
    5906     for (;;)
    5907     {
    5908         fAllFinished = true;
    5909         for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
    5910         {
    5911             pAhciPort = &pAhci->ahciPort[i];
    5912 
    5913             if (pAhciPort->pDrvBase)
    5914             {
    5915                 if (pAhciPort->fAsyncInterface)
    5916                     fAllFinished &= (pAhciPort->uActTasksActive == 0);
    5917                 else
    5918                     fAllFinished &= ((pAhciPort->uActTasksActive == 0) && (pAhciPort->fAsyncIOThreadIdle));
    5919 
    5920                 if (!fAllFinished)
    5921                     break;
    5922             }
    5923         }
    5924         if (   fAllFinished
    5925             || RTTimeMilliTS() - u64Start >= cMillies)
    5926             break;
    5927 
    5928         /* Wait for a port to signal idleness. */
    5929         int rc = RTSemEventWait(pAhci->hEvtIdle, 100 /*ms*/);
    5930         AssertMsg(RT_SUCCESS(rc) || rc == VERR_TIMEOUT, ("%Rrc\n", rc)); NOREF(rc);
    5931     }
    5932 
    5933     ASMAtomicWriteBool(&pAhci->fSignalIdle, false);
    5934     return fAllFinished;
     5888/**
     5889 * Checks if all asynchronous I/O is finished.
     5890 *
     5891 * @returns true if quiesced, false if busy.
     5892 * @param   pDevIns         The device instance.
     5893 */
     5894static bool ahciR3AllAsyncIOIsFinished(PPDMDEVINS pDevIns)
     5895{
     5896    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     5897
     5898    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ahciPort); i++)
     5899    {
     5900        PAHCIPort pThisPort = &pThis->ahciPort[i];
     5901        if (pThisPort->pDrvBase)
     5902        {
     5903            bool fFinished;
     5904            if (pThisPort->fAsyncInterface)
     5905                fFinished = (pThisPort->uActTasksActive == 0);
     5906            else
     5907                fFinished = ((pThisPort->uActTasksActive == 0) && (pThisPort->fAsyncIOThreadIdle));
     5908            if (!fFinished)
     5909               return false;
     5910        }
     5911    }
     5912    return true;
    59355913}
    59365914
     
    59395917    PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    59405918
    5941     if (!ahciWaitForAllAsyncIOIsFinished(pDevIns, 20000))
    5942         AssertMsgFailed(("One port is still active\n"));
     5919    Assert(ahciR3AllAsyncIOIsFinished(pDevIns));
    59435920
    59445921    for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
     
    59685945
    59695946    return VINF_SUCCESS;
     5947}
     5948
     5949/**
     5950 * Callback employed by ataSuspend and ataR3PowerOff.
     5951 *
     5952 * @returns true if we've quiesced, false if we're still working.
     5953 * @param   pDevIns     The device instance.
     5954 */
     5955static DECLCALLBACK(bool) ahciR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
     5956{
     5957    if (!ahciR3AllAsyncIOIsFinished(pDevIns))
     5958        return false;
     5959
     5960    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     5961    ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     5962    return true;
     5963}
     5964
     5965/**
     5966 * Common worker for ataSuspend and ataR3PowerOff.
     5967 */
     5968static void ahciR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
     5969{
     5970    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     5971
     5972    ASMAtomicWriteBool(&pThis->fSignalIdle, true);
     5973    if (!ahciR3AllAsyncIOIsFinished(pDevIns))
     5974        PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone);
     5975    else
     5976        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    59705977}
    59715978
     
    59785985static DECLCALLBACK(void) ahciSuspend(PPDMDEVINS pDevIns)
    59795986{
     5987    PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
     5988    Log(("%s:\n", __FUNCTION__));
     5989
     5990    ahciR3SuspendOrPowerOff(pDevIns);
     5991
     5992    for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
     5993        ataControllerSuspend(&pAhci->aCts[i]);
     5994}
     5995
     5996/**
     5997 * Resume notification.
     5998 *
     5999 * @param   pDevIns     The device instance data.
     6000 */
     6001static DECLCALLBACK(void) ahciResume(PPDMDEVINS pDevIns)
     6002{
    59806003    PAHCI    pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    5981 
    5982     if (!ahciWaitForAllAsyncIOIsFinished(pDevIns, 20000))
    5983         AssertMsgFailed(("AHCI: One port is still active\n"));
    59846004
    59856005    Log(("%s:\n", __FUNCTION__));
    59866006    for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
    5987     {
    5988         ataControllerSuspend(&pAhci->aCts[i]);
    5989     }
    5990     return;
    5991 }
    5992 
    5993 
    5994 /**
    5995  * Resume notification.
    5996  *
    5997  * @returns VBox status.
    5998  * @param   pDevIns     The device instance data.
    5999  */
    6000 static DECLCALLBACK(void) ahciResume(PPDMDEVINS pDevIns)
    6001 {
    6002     PAHCI    pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    6003 
    6004     Log(("%s:\n", __FUNCTION__));
    6005     for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
    6006     {
    60076007        ataControllerResume(&pAhci->aCts[i]);
    6008     }
    60096008    return;
    60106009}
     
    64006399
    64016400/**
    6402  * Reset notification.
     6401 * Common reset worker.
    64036402 *
    6404  * @returns VBox status.
    64056403 * @param   pDevIns     The device instance data.
    64066404 */
    6407 static DECLCALLBACK(void) ahciReset(PPDMDEVINS pDevIns)
     6405static int ahciR3ResetCommon(PPDMDEVINS pDevIns, bool fConstructor)
    64086406{
    64096407    PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    6410 
    6411     if (!ahciWaitForAllAsyncIOIsFinished(pDevIns, 20000))
    6412         AssertMsgFailed(("AHCI: One port is still active\n"));
    64136408
    64146409    ahciHBAReset(pAhci);
     
    64206415    for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
    64216416        ataControllerReset(&pAhci->aCts[i]);
     6417    return VINF_SUCCESS;
     6418}
     6419
     6420/**
     6421 * Callback employed by ahciReset.
     6422 *
     6423 * @returns true if we've quiesced, false if we're still working.
     6424 * @param   pDevIns     The device instance.
     6425 */
     6426static DECLCALLBACK(bool) ahciR3IsAsyncResetDone(PPDMDEVINS pDevIns)
     6427{
     6428    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     6429
     6430    if (!ahciR3AllAsyncIOIsFinished(pDevIns))
     6431        return false;
     6432    ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     6433
     6434    ahciR3ResetCommon(pDevIns, false /*fConstructor*/);
     6435    return true;
     6436}
     6437
     6438/**
     6439 * Reset notification.
     6440 *
     6441 * @param   pDevIns     The device instance data.
     6442 */
     6443static DECLCALLBACK(void) ahciReset(PPDMDEVINS pDevIns)
     6444{
     6445    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     6446
     6447    ASMAtomicWriteBool(&pThis->fSignalIdle, true);
     6448    if (!ahciR3AllAsyncIOIsFinished(pDevIns))
     6449        PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncResetDone);
     6450    else
     6451    {
     6452        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     6453        ahciR3ResetCommon(pDevIns, false /*fConstructor*/);
     6454    }
    64226455}
    64236456
     
    64326465    PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    64336466
    6434     if (!ahciWaitForAllAsyncIOIsFinished(pDevIns, 20000))
    6435         AssertMsgFailed(("AHCI: One port is still active\n"));
     6467    ahciR3SuspendOrPowerOff(pDevIns);
    64366468
    64376469    for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)
     
    65226554    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    65236555    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    6524     pThis->hEvtIdle  = NIL_RTSEMEVENT;
    65256556
    65266557    PCIDevSetVendorId    (&pThis->dev, 0x8086); /* Intel */
     
    66036634        return rc;
    66046635    }
    6605 
    6606     rc = RTSemEventCreate(&pThis->hEvtIdle);
    6607     AssertRCReturn(rc, rc);
    66086636
    66096637    /* Create the timer for command completion coalescing feature. */
     
    69506978        return rc;
    69516979
    6952     ahciReset(pDevIns);
    6953 
    6954     return rc;
     6980    return ahciR3ResetCommon(pDevIns, true /*fConstructor*/);
    69556981}
    69566982
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp

    r24624 r24749  
    12361236    GEN_CHECK_OFF(AHCI, aCts[1]);
    12371237    GEN_CHECK_OFF(AHCI, lock);
    1238     GEN_CHECK_OFF(AHCI, hEvtIdle);
    12391238    GEN_CHECK_OFF(AHCI, u32PortsInterrupted);
    12401239    GEN_CHECK_OFF(AHCI, fReset);
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