• Mohan Kumar's avatar
    ALSA: hda: Reset stream if DMA RUN bit not cleared · 7faa26c1
    Mohan Kumar authored
    Tegra HDA has FIFO size which can hold upto 10 audio frames to support
    DVFS. When HDA DMA RUN bit is set to 0 to stop the stream, the DMA RUN
    bit will be cleared to 0 only after transferring all the remaining audio
    frames queued up in the fifo. This is not in sync with spec which states
    the controller will stop transmitting(output) in the beginning of the
    next frame for the relevant stream.
    
    The above behavior with Tegra HDA was resulting in machine check error
    during the system suspend flow with active audio playback with below kernel
    error logs.
    [ 33.524583] mc-err: [mcerr] (hda) csr_hdar: EMEM address decode error
    [ 33.531088] mc-err: [mcerr] status = 0x20000015; addr = 0x00000000
    [ 33.537431] mc-err: [mcerr] secure: no, access-type: read, SMMU fault: none
    
    This was due to the fifo has more than one audio frame when the DMA
    RUN bit is set to 0 during system suspend flow and the timeout handling in
    snd_hdac_stream_sync() was not designed to handle this scenario. So the
    DMA will continue running even after timeout hit until all remaining
    audio frames in the fifo are transferred, but the suspend flow will try
    to reset the controller and turn off the hda clocks without the knowledge
    of the DMA is still running and could result in mc-err.
    
    The above issue can be resolved by doing stream reset with the help of
    snd_hdac_stream_reset() which would ensure the DMA RUN bit is cleared
    if the timeout was hit in snd_hdac_stream_sync().
    Signed-off-by: default avatarMohan Kumar <mkumard@nvidia.com>
    Link: https://lore.kernel.org/r/20200128051508.26064-1-mkumard@nvidia.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
    7faa26c1
hdac_stream.c 20.8 KB