VirtualBox

Changeset 89874 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 24, 2021 9:51:51 AM (3 years ago)
Author:
vboxsync
Message:

DevHda: Calculate cMsSchedulingHint based on the actual scheduling rather than some unused and obsolete timer frequency value. Removed the TimerHz config value. Cleanups. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHda.cpp

    r89873 r89874  
    47534753                                  "|BufSizeOutMs"
    47544754                                  "|InitialDelayMs"
    4755                                   "|TimerHz"
    47564755                                  "|DebugEnabled"
    47574756                                  "|DebugPathOut",
     
    47774776        return PDMDEV_SET_ERROR(pDevIns, VERR_OUT_OF_RANGE,
    47784777                                N_("HDA configuration error: 'BufSizeOutMs' is out of bound, max 2000 ms"));
    4779 
    4780     /** @todo uTimerHz isn't used for anything anymore. */
    4781     rc = pHlp->pfnCFGMQueryU16Def(pCfg, "TimerHz", &pThis->uTimerHz, HDA_TIMER_HZ_DEFAULT);
    4782     if (RT_FAILURE(rc))
    4783         return PDMDEV_SET_ERROR(pDevIns, rc,
    4784                                 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
    4785     if (pThis->uTimerHz != HDA_TIMER_HZ_DEFAULT)
    4786         LogRel(("HDA: Using custom device timer rate (%RU16Hz)\n", pThis->uTimerHz));
    47874778
    47884779    /** @devcfgm{hda,InitialDelayMs,uint16_t,0,256,12,ms}
  • trunk/src/VBox/Devices/Audio/DevHda.h

    r89873 r89874  
    129129    /** Current IRQ level. */
    130130    uint8_t                 u8IRQL;
    131     uint8_t                 abPadding[4];
    132     /** The device timer Hz rate. Defaults to HDA_TIMER_HZ_DEFAULT. */
    133     uint16_t                uTimerHz;
     131    uint8_t                 abPadding[4 + 2];
    134132    /** Number of milliseconds to delay kicking off the AIO when a stream starts.
    135133     * @sa InitialDelayMs config value.  */
  • trunk/src/VBox/Devices/Audio/DevHdaCommon.h

    r89869 r89874  
    107107 */
    108108
    109 /** Default timer frequency (in Hz).
    110  *
    111  *  20 Hz now seems enough for most setups, even with load on the guest.
    112  *  Raising the rate will produce more I/O load on the guest and therefore
    113  *  also will affect the performance.
    114  */
    115 #define HDA_TIMER_HZ_DEFAULT        100
    116 
    117 /** Default position adjustment (in audio samples).
    118  *
    119  * For snd_hda_intel (Linux guests), the first BDL entry always is being used as
    120  * so-called BDL adjustment, which can vary, and is being used for chipsets which
    121  * misbehave and/or are incorrectly implemented.
    122  *
    123  * The BDL adjustment entry *always* has the IOC (Interrupt on Completion) bit set.
    124  *
    125  * For Intel Baytrail / Braswell implementations the BDL default adjustment is 32 frames, whereas
    126  * for ICH / PCH it's only one (1) frame.
    127  *
    128  * See default_bdl_pos_adj() and snd_hdac_stream_setup_periods() for more information.
    129  *
    130  * By default we apply some simple heuristics in hdaStreamInit().
    131  */
    132 #define HDA_POS_ADJUST_DEFAULT      0
    133 
    134 /** HDA's (fixed) audio frame size in bytes.
    135  *  We only support 16-bit stereo frames at the moment. */
    136 #define HDA_FRAME_SIZE_DEFAULT      4
    137 
    138109/** Offset of the SD0 register map. */
    139110#define HDA_REG_DESC_SD0_BASE       0x80
  • trunk/src/VBox/Devices/Audio/DevHdaStream.cpp

    r89869 r89874  
    651651
    652652    /*
    653      * Calculate the transfer Hz for use in the circular buffer calculation.
     653     * Calculate the transfer Hz for use in the circular buffer calculation
     654     * and the average period for the scheduling hint.
    654655     */
    655656    uint32_t cbMaxPeriod = 0;
    656657    uint32_t cbMinPeriod = UINT32_MAX;
     658    uint64_t cTicks      = 0;
    657659    uint32_t cPeriods    = 0;
    658     for (uint32_t i = 0; i < pStreamShared->State.cSchedule; i++)
     660    for (uint32_t i = pStreamShared->State.cSchedulePrologue; i < pStreamShared->State.cSchedule; i++)
    659661    {
    660662        uint32_t cbPeriod = pStreamShared->State.aSchedule[i].cbPeriod;
     
    662664        cbMinPeriod = RT_MIN(cbMinPeriod, cbPeriod);
    663665        cPeriods   += pStreamShared->State.aSchedule[i].cLoops;
    664     }
     666        cTicks     += pStreamShared->State.aSchedule[i].cPeriodTicks * pStreamShared->State.aSchedule[i].cLoops;
     667    }
     668    /* Only consider the prologue in relation to the max period. */
     669    for (uint32_t i = 0; i < pStreamShared->State.cSchedulePrologue; i++)
     670        cbMaxPeriod = RT_MAX(cbMaxPeriod, pStreamShared->State.aSchedule[i].cbPeriod);
     671
     672    AssertLogRelReturn(cPeriods > 0, VERR_INTERNAL_ERROR_3);
    665673    uint64_t const cbTransferPerSec  = RT_MAX(PDMAudioPropsFramesToBytes(&pCfg->Props, pCfg->Props.uHz),
    666674                                              4096 /* zero div prevention: min is 6kHz, picked 4k in case I'm mistaken */);
     
    675683
    676684    pStreamShared->State.cbAvgTransfer = (uint32_t)(cbTotal + cPeriods - 1) / cPeriods;
     685
     686    /* Calculate the average scheduling period length in nanoseconds. */
     687    uint64_t const cTimerResolution = PDMDevHlpTimerGetFreq(pDevIns, pStreamShared->hTimer);
     688    Assert(cTimerResolution <= UINT32_MAX);
     689    uint64_t const cNsPerPeriod     = ASMMultU64ByU32DivByU32(cTicks / cPeriods, RT_NS_1SEC, cTimerResolution);
     690    AssertLogRelReturn(cNsPerPeriod > 0, VERR_INTERNAL_ERROR_3);
    677691
    678692    /* For input streams we must determin a pre-buffering requirement.
     
    687701     * Set up data transfer stuff.
    688702     */
    689 
    690     /* Assign the global device rate to the stream I/O timer as default. */
    691     pStreamShared->State.uTimerIoHz = pThis->uTimerHz;
    692     ASSERT_GUEST_LOGREL_MSG_STMT(pStreamShared->State.uTimerIoHz,
    693                                  ("I/O timer Hz rate for stream #%RU8 is invalid\n", uSD),
    694                                  pStreamShared->State.uTimerIoHz = HDA_TIMER_HZ_DEFAULT);
    695 
    696703    /* Set I/O scheduling hint for the backends. */
    697     /** @todo r=bird: derive this from the schedule instead of using the
    698      *        uTimerIoHz, as that's almost pure non-sense now. */
    699     pCfg->Device.cMsSchedulingHint = RT_MS_1SEC / pStreamShared->State.uTimerIoHz;
     704    pCfg->Device.cMsSchedulingHint = cNsPerPeriod > RT_NS_1MS ? (cNsPerPeriod + RT_NS_1MS / 2) / RT_NS_1MS : 1;
    700705    LogRel2(("HDA: Stream #%RU8 set scheduling hint for the backends to %RU32ms\n", uSD, pCfg->Device.cMsSchedulingHint));
    701 
    702706
    703707    /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
    704708    /** @todo r=bird: We use LPIB as-is here, so if it's not zero we have to
    705      *        locate the right place in the schedule and whatnot... */
     709     * locate the right place in the schedule and whatnot...
     710     *
     711     * This is a similar scenario as when loading state saved, btw.
     712     */
    706713    if (HDA_STREAM_REG(pThis, LPIB, uSD) != 0)
    707714        LogRel2(("HDA: Warning! Stream #%RU8 is set up with LPIB=%#RX32 instead of zero!\n", uSD, HDA_STREAM_REG(pThis, LPIB, uSD)));
     
    755762     *       channels we don't support / need to save space.
    756763     */
    757     uint32_t msCircBuf = RT_MS_1SEC * 6 / RT_MIN(uTransferHz, pStreamShared->State.uTimerIoHz);
    758     msCircBuf = RT_MAX(msCircBuf, pThis->msInitialDelay + RT_MS_1SEC * 6 / uTransferHz);
    759 
    760     uint32_t cbCircBuf = PDMAudioPropsMilliToBytes(&pCfg->Props, msCircBuf);
     764    uint32_t cbCircBuf = PDMAudioPropsMilliToBytes(&pCfg->Props, pThis->msInitialDelay + RT_MS_1SEC * 6 / uTransferHz);
    761765    LogRel2(("HDA: Stream #%RU8 default ring buffer size is %RU32 bytes / %RU64 ms\n",
    762766             uSD, cbCircBuf, PDMAudioPropsBytesToMilli(&pCfg->Props, cbCircBuf)));
  • trunk/src/VBox/Devices/Audio/DevHdaStream.h

    r89869 r89874  
    9696    /** Flag indicating if the stream is in running state or not. */
    9797    volatile bool           fRunning;
    98     /** The stream's I/O timer Hz rate. */
    99     uint16_t                uTimerIoHz;
    10098    /** How many interrupts are pending due to
    10199     *  BDLE interrupt-on-completion (IOC) bits set. */
    102100    uint8_t                 cTransferPendingInterrupts;
    103     /** Unused, padding. */
    104     uint8_t                 abPadding1[2];
    105101    /** Input streams only: Set when we switch from feeding the guest silence and
    106102     *  commits to proving actual audio input bytes. */
     
    108104    /** Input streams only: The number of bytes we need to prebuffer. */
    109105    uint32_t                cbInputPreBuffer;
    110     uint32_t                u32Padding2;
    111106    /** Timestamp (absolute, in timer ticks) of the last DMA data transfer.
    112107     * @note This is used for wall clock (WALCLK) calculations.  */
     
    159154    /** Current loop number within the current scheduling step.  */
    160155    uint32_t                idxScheduleLoop;
     156
     157    /** Aligning the next members on 16 bytes. */
     158    uint64_t                u64Padding;
    161159
    162160    /** Buffer descriptors and additional timer scheduling state.
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