From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E74E6C7EE23 for ; Thu, 11 May 2023 12:10:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237524AbjEKMKZ (ORCPT ); Thu, 11 May 2023 08:10:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237952AbjEKMKV (ORCPT ); Thu, 11 May 2023 08:10:21 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C00C6A25D for ; Thu, 11 May 2023 05:09:42 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-ba1b052e540so16489361276.3 for ; Thu, 11 May 2023 05:09:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1683806979; x=1686398979; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Gq50IKagmAfx+KtR1kRor/KE8cLkJvCa6loH1PRIiT0=; b=s+ibXT5LhfW0Hyd5StfD45uuSAvx2H35hDpVPqOWumUSnfgb134dW44DYQTgLH6880 Qb+kPoclvkP8Wre0VOySezhrld8bbiXeYV3QHpnqVstEYYfOZWqS5aJI/EpjJ6SZXfOY b9QWDFOt5zwBAxzL/I9XAM4IQSRsuPaW09RG0Zad4Mf8ek2BRVFrEcoymoKGP8wp1fk9 ImAAH6jR/E/s7O8CutcWKEMY/XG3HYzhvmU0gvEvSg9/rUe546yR4t45/mKklroGj6HA jPcIK5VNpzuyNey3AuoxcAgvbMYlb18wc6gUpAO2AkbX+4bXGxiWaRd+BAkn+LnYoQln Cwug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683806979; x=1686398979; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Gq50IKagmAfx+KtR1kRor/KE8cLkJvCa6loH1PRIiT0=; b=Johw7Xvr0NOcwTEECnA+8IgJe7mL3vJRwFAdgocSbb8fJxI5ajZ1P1MvSJloj5qUXO qypSlIq84viDptLCsmzckAR6QuVxGwpM/EQ3C0hPJxDCVfgMh3X1xJTU57s+JuR1+F1I 5P1bCFh2XuBnCb/SxK6DrQPUcHAelY+W4sBvNrLUk683BtQG5SRG4ZWzt/xn/6yM8BuM qJP7LQpW04DEOFdAtGFYRpM4RZfjZrc4rJJB+vaBdc8P9EWAFUsF10V1KYv6Ji0g35M8 4f0gkAkwluI5lcTKDKiW1kQzNh7v277ghq+BS9Cb1Dsouo2IqGiL8oPz7XjdVRg9/gOe Me/w== X-Gm-Message-State: AC+VfDypZpNYZ5knScMAk0KpN5pEmGJ+HYAUykvJ/4/Utnb53d29C5IJ aMUmNBlwkcQQMrUFZAELKFqZhXQQW6z9084i7Q== X-Google-Smtp-Source: ACHHUZ7GXRvobpmjcTV1wtH42bsAR8OSXx4rcv3iFvcVWxwI4sZT6AufYn5/awPTYWKCyvVEL5XHKRiPeMfsWd2itA== X-Received: from yixuanjiang.ntc.corp.google.com ([2401:fa00:fc:202:6c9a:64c9:7e44:6b1d]) (user=yixuanjiang job=sendgmr) by 2002:a25:abb0:0:b0:b9e:71a7:3bc9 with SMTP id v45-20020a25abb0000000b00b9e71a73bc9mr12788020ybi.10.1683806978838; Thu, 11 May 2023 05:09:38 -0700 (PDT) Date: Thu, 11 May 2023 20:08:40 +0800 In-Reply-To: <20230511120841.2096524-1-yixuanjiang@google.com> Mime-Version: 1.0 References: <20230511120841.2096524-1-yixuanjiang@google.com> X-Mailer: git-send-email 2.40.1.521.gf1e218fcd8-goog Message-ID: <20230511120841.2096524-6-yixuanjiang@google.com> Subject: [PATCH 5/6] ASoC: soc-pcm: test refcount before triggering From: yixuanjiang To: tiwai@suse.com, lgirdwood@gmail.com, broonie@kernel.org Cc: linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, Pierre-Louis Bossart , Kai Vehmanen , Bard Liao , Ranjani Sridharan , Yixuan Jiang , stable@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Pierre-Louis Bossart [ Upstream commit 848aedfdc6ba25ad5652797db9266007773e44dd ] On start/pause_release/resume, when more than one FE is connected to the same BE, it's possible that the trigger is sent more than once. This is not desirable, we only want to trigger a BE once, which is straightforward to implement with a refcount. For stop/pause/suspend, the problem is more complicated: the check implemented in snd_soc_dpcm_can_be_free_stop() may fail due to a conceptual deadlock when we trigger the BE before the FE. In this case, the FE states have not yet changed, so there are corner cases where the TRIGGER_STOP is never sent - the dual case of start where multiple triggers might be sent. This patch suggests an unconditional trigger in all cases, without checking the FE states, using a refcount protected by the BE PCM stream lock. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20211207173745.15850-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown Fixes: aa9ff6a4955f ("ASoC: soc-compress: Reposition and add pcm_mutex") Signed-off-by: Yixuan Jiang Cc: stable@vger.kernel.org # 5.15+ --- include/sound/soc-dpcm.h | 2 ++ sound/soc/soc-pcm.c | 53 +++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index e296a3949b18b..d963f3b608489 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -101,6 +101,8 @@ struct snd_soc_dpcm_runtime { enum snd_soc_dpcm_state state; int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ + + int be_start; /* refcount protected by BE stream pcm lock */ }; #define for_each_dpcm_fe(be, stream, _dpcm) \ diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7903516c89a6a..b6099d36518f5 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1630,7 +1630,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; goto unwind; } - + be->dpcm[stream].be_start = 0; be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; count++; } @@ -2116,14 +2116,21 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && + if (!be->dpcm[stream].be_start && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) goto next; + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start != 1) + goto next; + ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2131,9 +2138,15 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND)) goto next; + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start != 1) + goto next; + ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2141,9 +2154,15 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) goto next; + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start != 1) + goto next; + ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2152,12 +2171,18 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) goto next; - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_START) + be->dpcm[stream].be_start--; + + if (be->dpcm[stream].be_start != 0) goto next; ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_START) + be->dpcm[stream].be_start++; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; break; @@ -2165,12 +2190,15 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) goto next; - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + be->dpcm[stream].be_start--; + if (be->dpcm[stream].be_start != 0) goto next; ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start++; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND; break; @@ -2178,12 +2206,15 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) goto next; - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + be->dpcm[stream].be_start--; + if (be->dpcm[stream].be_start != 0) goto next; ret = soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start++; goto next; + } be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; break; -- 2.40.1.521.gf1e218fcd8-goog