• Takashi Iwai's avatar
    ASoC: dpcm: Fix race between FE/BE updates and trigger · ea9d0d77
    Takashi Iwai authored
    DPCM can update the FE/BE connection states totally asynchronously
    from the FE's PCM state.  Most of FE/BE state changes are protected by
    mutex, so that they won't race, but there are still some actions that
    are uncovered.  For example, suppose to switch a BE while a FE's
    stream is running.  This would call soc_dpcm_runtime_update(), which
    sets FE's runtime_update flag, then sets up and starts BEs, and clears
    FE's runtime_update flag again.
    
    When a device emits XRUN during this operation, the PCM core triggers
    snd_pcm_stop(XRUN).  Since the trigger action is an atomic ops, this
    isn't blocked by the mutex, thus it kicks off DPCM's trigger action.
    It eventually updates and clears FE's runtime_update flag while
    soc_dpcm_runtime_update() is running concurrently, and it results in
    confusion.
    
    Usually, for avoiding such a race, we take a lock.  There is a PCM
    stream lock for that purpose.  However, as already mentioned, the
    trigger action is atomic, and we can't take the lock for the whole
    soc_dpcm_runtime_update() or other operations that include the lengthy
    jobs like hw_params or prepare.
    
    This patch provides an alternative solution.  This adds a way to defer
    the conflicting trigger callback to be executed at the end of FE/BE
    state changes.  For doing it, two things are introduced:
    
    - Each runtime_update state change of FEs is protected via PCM stream
      lock.
    - The FE's trigger callback checks the runtime_update flag.  If it's
      not set, the trigger action is executed there.  If set, mark the
      pending trigger action and returns immediately.
    - At the exit of runtime_update state change, it checks whether the
      pending trigger is present.  If yes, it executes the trigger action
      at this point.
    Reported-and-tested-by: default avatarQiao Zhou <zhouqiao@marvell.com>
    Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
    Acked-by: default avatarLiam Girdwood <liam.r.girdwood@linux.intel.com>
    Signed-off-by: default avatarMark Brown <broonie@kernel.org>
    Cc: stable@vger.kernel.org
    ea9d0d77
soc-dpcm.h 4.73 KB