diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-11-07 12:39:53 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-17 13:18:50 -0800 |
commit | d8bd61294823b6e6604fc91217f9306685e11924 (patch) | |
tree | 4b776ed7ea2deacbf5c2965159689b508864f956 | |
parent | 35522de8494e895c621794f313a1c0526f1c18bd (diff) |
ALSA: usb-audio: Use rwsem for disconnect protection
commit 34f3c89fda4fba9fe689db22253ca8db2f5e6386 upstream.
Replace mutex with rwsem for codec->shutdown protection so that
concurrent accesses are allowed.
Also add the protection to snd_usb_autosuspend() and
snd_usb_autoresume(), too.
Reported-by: Matthieu CASTET <matthieu.castet@parrot.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | sound/usb/card.c | 12 | ||||
-rw-r--r-- | sound/usb/mixer.c | 12 | ||||
-rw-r--r-- | sound/usb/pcm.c | 12 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 2 |
4 files changed, 21 insertions, 17 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 4a469f0cb6d..486b4a67772 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, } mutex_init(&chip->mutex); - mutex_init(&chip->shutdown_mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; @@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, card = chip->card; mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; chip->num_interfaces--; if (chip->num_interfaces <= 0) { @@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); } } @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c2ef11ccd66..298070e8f2d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(cval->mixer->chip); return err; } @@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); if (chip->shutdown) ret = -ENODEV; else { @@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, idx, buf, size); } - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); if (ret < 0) { @@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); return err; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0de406a798f..ee3c15c546e 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -474,7 +474,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -512,7 +512,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, } unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } @@ -528,12 +528,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (!subs->stream->chip->shutdown) { stop_endpoints(subs, 0, 1, 1); deactivate_endpoints(subs); } - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -553,7 +553,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -582,7 +582,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ret = start_endpoints(subs, 1); unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250..ef42797f56f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio { struct usb_interface *pm_intf; u32 usb_id; struct mutex mutex; - struct mutex shutdown_mutex; + struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; |