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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html