From nobody Wed Feb 11 00:54:47 2026 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 4A08BC77B7C for ; Thu, 11 May 2023 12:10:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237949AbjEKMK1 (ORCPT ); Thu, 11 May 2023 08:10:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237782AbjEKMKV (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 F38FC55B3 for ; Thu, 11 May 2023 05:09:41 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-b9a7553f95dso16759536276.2 for ; Thu, 11 May 2023 05:09:41 -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=cty1WuR5mOLLKKCpEtyxU/1wc+cUlpR3XriC0n9WjzBL4D7ylMo2dTVlkWJG62sfgg I3rdgc6i0fclN4TLFEy2H3XX91Zgf/KlzOFPw7aWTtGaPxx8Gy0CWiVKpp3xfvnqJFmk ux3EcUA7eNyMpoNnLg/MpNxJ90KV/cMA3oKDf3EUZewnYQ9HnuuzQDjux3jiIdRha4BP +jixZwdude3btzXPIv4a6bhjkbmoq5vbE+uVlXgrJB20LilBivC0AxCKJJKxhh0guMx9 eVFbgkDg+pm4m6tPJMRiKWk0NHpS+qPYO4vE2GkvkBu1yEmRg4xq3SRSLDHecG4ptZq8 wxfQ== X-Gm-Message-State: AC+VfDxGXGhcPivyt4hg7WG5QbMHKhg6dqhvlMXM+qdGf0LTvP34b+LG Xyfq8ROB+3b3BQ4yaDWUrvW1LJ+t6t5QC2wbXg== 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 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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; =20 int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ + + int be_start; /* refcount protected by BE stream pcm lock */ }; =20 #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 *f= e, int stream) be->dpcm[stream].state =3D SND_SOC_DPCM_STATE_CLOSE; goto unwind; } - + be->dpcm[stream].be_start =3D 0; be->dpcm[stream].state =3D SND_SOC_DPCM_STATE_OPEN; count++; } @@ -2116,14 +2116,21 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime = *fe, int stream, =20 switch (cmd) { case SNDRV_PCM_TRIGGER_START: - if ((be->dpcm[stream].state !=3D SND_SOC_DPCM_STATE_PREPARE) && + if (!be->dpcm[stream].be_start && + (be->dpcm[stream].state !=3D SND_SOC_DPCM_STATE_PREPARE) && (be->dpcm[stream].state !=3D SND_SOC_DPCM_STATE_STOP) && (be->dpcm[stream].state !=3D SND_SOC_DPCM_STATE_PAUSED)) goto next; =20 + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start !=3D 1) + goto next; + ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } =20 be->dpcm[stream].state =3D 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 !=3D SND_SOC_DPCM_STATE_SUSPEND)) goto next; =20 + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start !=3D 1) + goto next; + ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } =20 be->dpcm[stream].state =3D 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 !=3D SND_SOC_DPCM_STATE_PAUSED)) goto next; =20 + be->dpcm[stream].be_start++; + if (be->dpcm[stream].be_start !=3D 1) + goto next; + ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start--; goto next; + } =20 be->dpcm[stream].state =3D 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 !=3D SND_SOC_DPCM_STATE_PAUSED)) goto next; =20 - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + if (be->dpcm[stream].state =3D=3D SND_SOC_DPCM_STATE_START) + be->dpcm[stream].be_start--; + + if (be->dpcm[stream].be_start !=3D 0) goto next; =20 ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + if (be->dpcm[stream].state =3D=3D SND_SOC_DPCM_STATE_START) + be->dpcm[stream].be_start++; goto next; + } =20 be->dpcm[stream].state =3D 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 !=3D SND_SOC_DPCM_STATE_START) goto next; =20 - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + be->dpcm[stream].be_start--; + if (be->dpcm[stream].be_start !=3D 0) goto next; =20 ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start++; goto next; + } =20 be->dpcm[stream].state =3D 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 !=3D SND_SOC_DPCM_STATE_START) goto next; =20 - if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + be->dpcm[stream].be_start--; + if (be->dpcm[stream].be_start !=3D 0) goto next; =20 ret =3D soc_pcm_trigger(be_substream, cmd); - if (ret) + if (ret) { + be->dpcm[stream].be_start++; goto next; + } =20 be->dpcm[stream].state =3D SND_SOC_DPCM_STATE_PAUSED; break; --=20 2.40.1.521.gf1e218fcd8-goog