From: Matthieu CASTET <matthieu.castet-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
To: Takashi Iwai <tiwai-l3A5Bk7waGM@public.gmane.org>
Cc: USB list <linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
ALSA devel <alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org>,
Greg KH
<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Clemens Ladisch <clemens-P6GI/4k7KOmELgA04lAiVw@public.gmane.org>
Subject: Re: usb audio race at disconnect time
Date: Fri, 12 Oct 2012 17:42:19 +0200 [thread overview]
Message-ID: <50783A5B.9090009@parrot.com> (raw)
In-Reply-To: <s5hvceh9d0v.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
Hi,
Takashi Iwai a écrit :
> [Added Daniel and Clemens in the loop]
>
>
> I don't think this is needed.
>
> So... the below is a quick hack I did without testing at all.
> Hopefully this can give some advance.
Thanks for the quick patch.
The patch didn't apply cleany of linus tree, of which tree is based your patch ?
It solve the race in snd_usb_hw_params.
But I wonder if snd_usb_substream_playback_trigger,
snd_usb_substream_capture_trigger, snd_usb_pcm_pointer are safe : they don't
take shutdown_mutex.
Also it is hard to check if everything is safe. Sometimes the chip->shutdown is
far from the shutdown_mutex. For example snd_usb_pcm_open take shutdown_mutex,
but the check is done in snd_usb_autoresume.
I will do more testing.
Thanks,
Matthieu
>
>
> Takashi
>
> ---
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 561bb74..115484e 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -131,9 +131,13 @@ static void snd_usb_stream_disconnect(struct list_head *head)
> subs = &as->substream[idx];
> if (!subs->num_formats)
> continue;
> + if (subs->pcm_substream)
> + snd_pcm_stream_lock_irq(subs->pcm_substream);
> subs->interface = -1;
> subs->data_endpoint = NULL;
> subs->sync_endpoint = NULL;
> + if (subs->pcm_substream)
> + snd_pcm_stream_unlock_irq(subs->pcm_substream);
> }
> }
>
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index 55e19e1..01e82ac 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -444,7 +444,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
> {
> int ret;
>
> - mutex_lock(&subs->stream->chip->shutdown_mutex);
> /* format changed */
> stop_endpoints(subs, 0, 0, 0);
> ret = snd_usb_endpoint_set_params(subs->data_endpoint,
> @@ -455,7 +454,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
> subs->cur_audiofmt,
> subs->sync_endpoint);
> if (ret < 0)
> - goto unlock;
> + return ret;
>
> if (subs->sync_endpoint)
> ret = snd_usb_endpoint_set_params(subs->data_endpoint,
> @@ -466,8 +465,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
> subs->cur_audiofmt,
> NULL);
>
> -unlock:
> - mutex_unlock(&subs->stream->chip->shutdown_mutex);
> return ret;
> }
>
> @@ -488,10 +485,15 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
> struct audioformat *fmt;
> int ret;
>
> + mutex_lock(&subs->stream->chip->shutdown_mutex);
> + if (subs->stream->chip->shutdown) {
> + ret = -ENODEV;
> + goto unlock;
> + }
> ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
> params_buffer_bytes(hw_params));
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> subs->pcm_format = params_format(hw_params);
> subs->period_bytes = params_period_bytes(hw_params);
> @@ -502,17 +504,20 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
> if (!fmt) {
> snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
> subs->pcm_format, subs->cur_rate, subs->channels);
> - return -EINVAL;
> + ret = -EINVAL;
> + goto unlock;
> }
>
> if ((ret = set_format(subs, fmt)) < 0)
> - return ret;
> + goto unlock;
>
> subs->interface = fmt->iface;
> subs->altset_idx = fmt->altset_idx;
> subs->need_setup_ep = true;
>
> - return 0;
> + unlock:
> + mutex_unlock(&subs->stream->chip->shutdown_mutex);
> + return ret;
> }
>
> /*
> @@ -547,17 +552,26 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
> struct usb_interface *iface;
> int ret;
>
> + mutex_lock(&subs->stream->chip->shutdown_mutex);
> + if (subs->stream->chip->shutdown) {
> + ret = -ENODEV;
> + goto unlock;
> + }
> +
> if (! subs->cur_audiofmt) {
> snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
> - return -ENXIO;
> + ret = -ENXIO;
> + goto unlock;
> }
>
> - if (snd_BUG_ON(!subs->data_endpoint))
> - return -EIO;
> + if (snd_BUG_ON(!subs->data_endpoint)) {
> + ret = -EIO;
> + goto unlock;
> + }
>
> ret = set_format(subs, subs->cur_audiofmt);
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
> alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
> @@ -567,12 +581,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
> subs->cur_audiofmt,
> subs->cur_rate);
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> if (subs->need_setup_ep) {
> ret = configure_endpoint(subs);
> if (ret < 0)
> - return ret;
> + goto unlock;
> subs->need_setup_ep = false;
> }
>
> @@ -592,8 +606,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
> /* for playback, submit the URBs now; otherwise, the first hwptr_done
> * updates for all URBs would happen at the same time when starting */
> if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
> - return start_endpoints(subs, 1);
> + ret = start_endpoints(subs, 1);
>
> + unlock:
> + mutex_unlock(&subs->stream->chip->shutdown_mutex);
> return 0;
> }
>
> @@ -980,14 +996,18 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
> struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
> struct snd_pcm_runtime *runtime = substream->runtime;
> struct snd_usb_substream *subs = &as->substream[direction];
> + int ret;
>
> + mutex_lock(&as->chip->shutdown_mutex);
> subs->interface = -1;
> subs->altset_idx = 0;
> runtime->hw = snd_usb_hardware;
> runtime->private_data = subs;
> subs->pcm_substream = substream;
> /* runtime PM is also done there */
> - return setup_hw_info(runtime, subs);
> + ret = setup_hw_info(runtime, subs);
> + mutex_unlock(&as->chip->shutdown_mutex);
> + return ret;
> }
>
> static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
> @@ -995,6 +1015,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
> struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
> struct snd_usb_substream *subs = &as->substream[direction];
>
> + mutex_lock(&as->chip->shutdown_mutex);
> stop_endpoints(subs, 0, 0, 0);
>
> if (!as->chip->shutdown && subs->interface >= 0) {
> @@ -1004,6 +1025,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
>
> subs->pcm_substream = NULL;
> snd_usb_autosuspend(subs->stream->chip);
> + mutex_unlock(&as->chip->shutdown_mutex);
>
> return 0;
> }
> @@ -1222,6 +1244,9 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
> {
> struct snd_usb_substream *subs = substream->runtime->private_data;
>
> + if (subs->stream->chip->shutdown)
> + return -ENODEV;
> +
> switch (cmd) {
> case SNDRV_PCM_TRIGGER_START:
> case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2012-10-12 15:42 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-11 15:17 usb audio race at disconnect time Matthieu CASTET
[not found] ` <5076E327.5030503-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-11 16:01 ` Alan Stern
2012-10-11 16:41 ` Takashi Iwai
[not found] ` <s5hvceh9d0v.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
2012-10-12 14:31 ` [alsa-devel] " Takashi Iwai
2012-10-12 15:42 ` Matthieu CASTET [this message]
[not found] ` <50783A5B.9090009-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-13 8:31 ` Takashi Iwai
[not found] ` <s5h626eixid.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
2012-10-15 17:41 ` Matthieu CASTET
[not found] ` <507C4AD4.2090400-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-15 18:45 ` Takashi Iwai
[not found] ` <s5hwqyrh8vb.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
2012-10-16 15:16 ` Takashi Iwai
2012-10-16 16:01 ` Matthieu CASTET
[not found] ` <507D84C9.9070405-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-16 16:04 ` Takashi Iwai
[not found] ` <s5ha9vm4d46.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
2012-10-18 15:39 ` Matthieu CASTET
[not found] ` <50802299.9080004-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-19 20:57 ` Takashi Iwai
2012-10-29 14:17 ` Takashi Iwai
[not found] ` <s5h4nlduzvc.wl%tiwai-l3A5Bk7waGM@public.gmane.org>
2012-10-30 10:52 ` Matthieu CASTET
[not found] ` <508FB171.7030007-ITF29qwbsa/QT0dZR+AlfA@public.gmane.org>
2012-10-30 11:02 ` Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50783A5B.9090009@parrot.com \
--to=matthieu.castet-itf29qwbsa/qt0dzr+alfa@public.gmane.org \
--cc=alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org \
--cc=clemens-P6GI/4k7KOmELgA04lAiVw@public.gmane.org \
--cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
--cc=linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=tiwai-l3A5Bk7waGM@public.gmane.org \
--cc=zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.