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 X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7467C5DF60 for ; Thu, 7 Nov 2019 08:06:12 +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 5E12F206DF for ; Thu, 7 Nov 2019 08:06:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="DFzjk0A4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5E12F206DF Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@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 5CED4166C; Thu, 7 Nov 2019 09:05:20 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5CED4166C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573113970; bh=+7ecc9YyDuKVNlNpJuXdbmUn3865TZwu8z30v0JoxYo=; h=Date:From:To:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=DFzjk0A4XHo1lc001Bi7ThjSq+LSZ/hNmU9HDABUA266P/b3kWrzike8ct96RYY/D wknPc3DMRW/CEN8SEi5yIs3GReHj+XpFdcpJ76xzPNF9OcVk/bnhFyodlqrj9QblBY s3sHFjSy5wTn9cb6P9FQakjjo0nlmpW0xc3KSWBs= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E36AEF800F3; Thu, 7 Nov 2019 09:05:19 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A090BF8049B; Thu, 7 Nov 2019 09:05:18 +0100 (CET) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 4DBCFF800F3 for ; Thu, 7 Nov 2019 09:05:15 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4DBCFF800F3 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 3D572AD07; Thu, 7 Nov 2019 08:05:15 +0000 (UTC) Date: Thu, 07 Nov 2019 09:05:14 +0100 Message-ID: From: Takashi Iwai To: Andrew Gabbasov In-Reply-To: <20191105143218.5948-8-andrew_gabbasov@mentor.com> References: <20191105143218.5948-1-andrew_gabbasov@mentor.com> <20191105143218.5948-2-andrew_gabbasov@mentor.com> <20191105143218.5948-3-andrew_gabbasov@mentor.com> <20191105143218.5948-4-andrew_gabbasov@mentor.com> <20191105143218.5948-5-andrew_gabbasov@mentor.com> <20191105143218.5948-6-andrew_gabbasov@mentor.com> <20191105143218.5948-7-andrew_gabbasov@mentor.com> <20191105143218.5948-8-andrew_gabbasov@mentor.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") Cc: Timo Wischer , alsa-devel@alsa-project.org, Takashi Iwai , linux-kernel@vger.kernel.org Subject: Re: [alsa-devel] [PATCH v2 7/8] ALSA: aloop: Support selection of snd_timer instead of jiffies 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: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" On Tue, 05 Nov 2019 15:32:17 +0100, Andrew Gabbasov wrote: > @@ -102,6 +106,13 @@ struct loopback_cable { > unsigned int pause; > /* timer specific */ > struct loopback_ops *ops; > + /* If sound timer is used */ > + struct { > + int owner; The term "owner" is a bit confusing here. It seems holding the PCM direction, but most people expect it being a process-id or something like that from the word. > + struct snd_timer_id id; > + struct tasklet_struct event_tasklet; You don't need to make own tasklet. The timer core calls it via tasklet in anyway unless you pass SNDRV_TIMER_IFLG_FAST -- see below. And the tasklet is no longer recommended infrastructure in the recent kernel, we should avoid it as much as possible. > struct loopback_setup { > @@ -122,6 +133,7 @@ struct loopback { > struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; > struct snd_pcm *pcm[2]; > struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; > + char *timer_source; This can be const char *, I suppose. > +static void loopback_snd_timer_period_elapsed( > + struct loopback_cable * const cable, > + const int event, const unsigned long resolution) > +{ > + struct loopback_pcm *dpcm_play = > + cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; > + struct loopback_pcm *dpcm_capt = > + cable->streams[SNDRV_PCM_STREAM_CAPTURE]; You shouldn't assign them outside the cable->lock. > + struct snd_pcm_runtime *valid_runtime; > + unsigned int running, elapsed_bytes; > + unsigned long flags; > + > + spin_lock_irqsave(&cable->lock, flags); > + running = cable->running ^ cable->pause; > + /* no need to do anything if no stream is running */ > + if (!running) { > + spin_unlock_irqrestore(&cable->lock, flags); > + return; > + } > + > + if (event == SNDRV_TIMER_EVENT_MSTOP) { > + if (!dpcm_play || !dpcm_play->substream || > + !dpcm_play->substream->runtime || > + !dpcm_play->substream->runtime->status || Would these conditions really happen? > + dpcm_play->substream->runtime->status->state != > + SNDRV_PCM_STATE_DRAINING) { What's special with DRAINING state? The code doesn't show or explain it. And for other conditions, we keep going even if the event is MSTOP? > + spin_unlock_irqrestore(&cable->lock, flags); > + return; > + } > + } > + > + valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? > + dpcm_play->substream->runtime : > + dpcm_capt->substream->runtime; > + > + /* resolution is only valid for SNDRV_TIMER_EVENT_TICK events */ > + if (event == SNDRV_TIMER_EVENT_TICK) { > + /* The hardware rules guarantee that playback and capture period > + * are the same. Therefore only one device has to be checked > + * here. > + */ > + if (loopback_snd_timer_check_resolution(valid_runtime, > + resolution) < 0) { > + spin_unlock_irqrestore(&cable->lock, flags); > + if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) > + snd_pcm_stop_xrun(dpcm_play->substream); > + if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) > + snd_pcm_stop_xrun(dpcm_capt->substream); Referencing outside the lock isn't really safe. In the case of jiffies timer code, it's a kind of OK because it's done in the timer callback function that is assigned for each stream open -- that is, the stream runtime is guaranteed to be present in the timer callback. But I'm not sure about your case... > @@ -749,6 +1037,152 @@ static struct loopback_ops loopback_jiffies_timer_ops = { > .dpcm_info = loopback_jiffies_timer_dpcm_info, > }; > > +static int loopback_parse_timer_id(const char * const str, > + struct snd_timer_id *tid) > +{ > + /* [:](|)[{.,}[{.,}]] */ > + const char * const sep_dev = ".,"; > + const char * const sep_pref = ":"; > + const char *name = str; > + char save, *sep; > + int card = 0, device = 0, subdevice = 0; > + int err; > + > + sep = strpbrk(str, sep_pref); > + if (sep) > + name = sep + 1; > + sep = strpbrk(name, sep_dev); > + if (sep) { > + save = *sep; > + *sep = '\0'; > + } > + err = kstrtoint(name, 0, &card); > + if (err == -EINVAL) { > + /* Must be the name, not number */ > + for (card = 0; card < snd_ecards_limit; card++) { > + if (snd_cards[card] && > + !strcmp(snd_cards[card]->id, name)) { > + err = 0; > + break; > + } > + } > + } As kbuildbot reported, this is obviously broken with the recent kernel. snd_cards[] is no longer exported! And I don't want to export again. IOW, if we need this kind of thing, it's better to modify the existing code in sound/core/init.c and export that function. > +/* call in loopback->cable_lock */ > +static int loopback_snd_timer_open(struct loopback_pcm *dpcm) > +{ > + int err = 0; > + unsigned long flags; > + struct snd_timer_id tid = { > + .dev_class = SNDRV_TIMER_CLASS_PCM, > + .dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION, > + }; > + struct snd_timer_instance *timer = NULL; Why initialing to NULL here? > + spin_lock_irqsave(&dpcm->cable->lock, flags); You need no irqsave version but spin_lock_irq() for the context like open/close that is guaranteed to be sleepable. > + spin_lock_irqsave(&dpcm->cable->lock, flags); > + > + /* The callback has to be called from another tasklet. If > + * SNDRV_TIMER_IFLG_FAST is specified it will be called from the > + * snd_pcm_period_elapsed() call of the selected sound card. Well, you're the one who specifies SNDRV_TIMER_IFLG_XXX, so you know that the flag isn't set. So tasklet makes little sense. > + * snd_pcm_period_elapsed() helds snd_pcm_stream_lock_irqsave(). > + * Due to our callback loopback_snd_timer_function() also calls > + * snd_pcm_period_elapsed() which calls snd_pcm_stream_lock_irqsave(). > + * This would end up in a dead lock. > + */ > + timer->flags |= SNDRV_TIMER_IFLG_AUTO; > + timer->callback = loopback_snd_timer_function; > + timer->callback_data = (void *)dpcm->cable; > + timer->ccallback = loopback_snd_timer_event; This reminds me that we need a safer way to assign these stuff in general... But it's above this patch set, in anyway. thanks, Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org https://mailman.alsa-project.org/mailman/listinfo/alsa-devel