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>
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 4f49ca7..4a99f6c 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -376,7 +376,7 @@
 		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;
@@ -406,7 +406,7 @@
 	}
 
 unlock:
-	mutex_unlock(&subs->stream->chip->shutdown_mutex);
+	up_read(&subs->stream->chip->shutdown_rwsem);
 	return ret;
 }
 
@@ -422,9 +422,9 @@
 	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);
 	snd_usb_release_substream_urbs(subs, 0);
-	mutex_unlock(&subs->stream->chip->shutdown_mutex);
+	up_read(&subs->stream->chip->shutdown_rwsem);
 	return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
 
@@ -444,7 +444,7 @@
 		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;
@@ -463,7 +463,7 @@
 
 	ret = snd_usb_substream_prepare(subs, runtime);
  unlock:
-	mutex_unlock(&subs->stream->chip->shutdown_mutex);
+	up_read(&subs->stream->chip->shutdown_rwsem);
 	return ret;
 }