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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D42F3C433F5 for ; Thu, 7 Oct 2021 15:01:15 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0C81661130 for ; Thu, 7 Oct 2021 15:01:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0C81661130 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A9B859F6; Thu, 7 Oct 2021 17:00:21 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A9B859F6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1633618871; bh=EKPw2+Q8p/dmJTotY+GUcGwzooOFsFxKIzZXNi7xPIw=; h=Date:From:To:Subject:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=tT3giTzj3nDjHp+edzwDi6f9DrmzD+1nP85UmKO6wKrKdvMKN1wucxRxTpQ8sx+oN v5opbS0WG7/utTnlL3StiPr9lh+KU8J9lTaC1OM+zjxLQJ8kLIfSZCPMSRBD/A/mUN KjsHffdjIj/pzoXQIxdq7GYey71oKiEzaWx0X52M= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 26BB2F80259; Thu, 7 Oct 2021 17:00:21 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 131C7F8027D; Thu, 7 Oct 2021 17:00:19 +0200 (CEST) Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CC3BDF800FE for ; Thu, 7 Oct 2021 17:00:04 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CC3BDF800FE Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NupRC1ma"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="7ULUvI3W" Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id EEA9D224EE; Thu, 7 Oct 2021 14:59:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1633618798; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=In7Jg+0s7uAlU4Nky6HWQvAivfZLVLAuCYADx2vHHlA=; b=NupRC1mado0OdVr62uRJeYWMSiB+5XspTQJ5cNJ/xpbvDUC5g250pcCwbAh6iIKHWOp4Yp OXttSfCIluJdhTeOxA2Akl53Dhh93JOo65EEsEBdZee4AbBliqGuHLiLaye7Vj7M/wXhjd tqA5h/n0r5sd+jm/i251jJ5bsfGlVGk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1633618798; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=In7Jg+0s7uAlU4Nky6HWQvAivfZLVLAuCYADx2vHHlA=; b=7ULUvI3WJRrOTBKUn1ynHa2xd2ZhTYkMvtFonFC6xKosSGHTSbaGcn/79Ov4mtuy2nVunh T0Xc3qQvI1I91RBA== Received: from alsa1.suse.de (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id 5E215A3B81; Thu, 7 Oct 2021 14:59:58 +0000 (UTC) Date: Thu, 07 Oct 2021 16:59:58 +0200 Message-ID: From: Takashi Iwai To: Pierre-Louis Bossart Subject: Re: [RFC PATCH v2 0/5] ASoC: soc-pcm: fix trigger race conditions with shared BE In-Reply-To: References: <20211004225441.233375-1-pierre-louis.bossart@linux.intel.com> <1efa1c31-7342-05f8-5f73-95e2462d4179@linux.intel.com> <3683cf39-632b-50df-c65d-63779c464850@nvidia.com> <11257d77-9975-3b00-94da-5dc1b5c95fc6@linux.intel.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Cc: alsa-devel@alsa-project.org, Kuninori Morimoto , Sameer Pujar , vkoul@kernel.org, broonie@kernel.org, Gyeongtaek Lee , Peter Ujfalusi X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" On Thu, 07 Oct 2021 15:31:49 +0200, Pierre-Louis Bossart wrote: > > > >> Takashi, Mark, do you think that an all/none assumption on FE nonatomic > >> properties would make sense? > > > > As long as BE's are updated from FE's PCM callback, BE has to follow > > the atomicity of its FE, so we can't assume all or none globally. > > A BE may have more than one FEs. That's precisely the point of > mixers/demux, and if the BE has FEs with different 'atomicity' then I > don't see how locking can work: the BE operations are run in the context > of each of its FE, typically using the following loop: > > for_each_dpcm_be(fe, stream, dpcm) { > do_something(); > } Do we really have the cases where FEs have different atomicity? I don't think it's a valid configuration, and we should catch it via WARN_ON() or such. > Applications will view multiple FEs as completely independent. They may > be opened/prepared/started/stopped/paused as needed. When the BE is > shared, then there is a need for consistency, such as starting the BE > when the first FE becomes active and stopping it when the last FE stops. > > > How is the expected lock granularity and the protection context? Do > > we need a card global lock/mutex, or is it specific to each BE > > substream? > > We already have a dpcm_lock at the card level, which protects the > addition of BEs and BE states. That spin_lock is fine for most cases. > > The only real problem is the trigger, which is currently completely > unprotected: we have to serialize the BE triggers, otherwise you could > STOP before you START due to scheduling, or other problems that I saw in > my SoundWire tests with two START triggers, or the STOP never sent. So it's about calling triggers to the same BE stream concurrently? If that's the case, can't we simply protect the trigger handling of each BE like below? > But how to do this serialization is unclear... > > A lateral thinking approach would be to decouple the BEs entirely, and > have the FEs 'signal' their change of state. The BE 'thread' run in the > BE context would then serialize the requests and perform all the BE > operations, and the same approach could be chained. I am afraid that > would be a complete rewrite of DPCM, but maybe we have to do so anyways > if we can't support a basic case of a mixer with 2 streams :-) Well, let's see whether we can get some improvements by a simple change at first. Takashi --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1998,6 +1998,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, { struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; + unsigned long flags; int ret = 0; for_each_dpcm_be(fe, stream, dpcm) { @@ -2006,9 +2007,11 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, be = dpcm->be; be_substream = snd_soc_dpcm_get_substream(be, stream); + snd_pcm_stream_lock_irqsave(be_substream, flags); + /* is this op for this BE ? */ if (!snd_soc_dpcm_be_can_update(fe, be, stream)) - continue; + goto unlock; dev_dbg(be->dev, "ASoC: trigger BE %s cmd %d\n", be->dai_link->name, cmd); @@ -2018,77 +2021,81 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, if ((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)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; case SNDRV_PCM_TRIGGER_RESUME: if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; case SNDRV_PCM_TRIGGER_STOP: if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) - continue; + goto unlock; if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; break; case SNDRV_PCM_TRIGGER_SUSPEND: if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) - continue; + goto unlock; if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) - continue; + goto unlock; if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) - continue; + goto unlock; ret = soc_pcm_trigger(be_substream, cmd); if (ret) - goto end; + goto unlock; be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; break; } + unlock: + snd_pcm_stream_unlock_irqrestore(be_substream, flags); + if (ret < 0) + break; } -end: + if (ret < 0) dev_err(fe->dev, "ASoC: %s() failed at %s (%d)\n", __func__, be->dai_link->name, ret);