]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.6.7/alsa-usb-audio-use-rwsem-for-disconnect-protection.patch
Linux 3.6.7
[thirdparty/kernel/stable-queue.git] / releases / 3.6.7 / alsa-usb-audio-use-rwsem-for-disconnect-protection.patch
CommitLineData
903eef9e
GKH
1From tiwai@suse.de Wed Nov 7 15:57:25 2012
2From: tiwai@suse.de
3Date: Wed, 7 Nov 2012 12:39:53 +0100
4Subject: ALSA: usb-audio: Use rwsem for disconnect protection
5To: stable@vger.kernel.org
6
7From: Takashi Iwai <tiwai@suse.de>
8
9commit 34f3c89fda4fba9fe689db22253ca8db2f5e6386 upstream.
10
11Replace mutex with rwsem for codec->shutdown protection so that
12concurrent accesses are allowed.
13
14Also add the protection to snd_usb_autosuspend() and
15snd_usb_autoresume(), too.
16
17Reported-by: Matthieu CASTET <matthieu.castet@parrot.com>
18Signed-off-by: Takashi Iwai <tiwai@suse.de>
19Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20---
21 sound/usb/card.c | 12 ++++++++----
22 sound/usb/mixer.c | 12 ++++++------
23 sound/usb/pcm.c | 12 ++++++------
24 sound/usb/usbaudio.h | 2 +-
25 4 files changed, 21 insertions(+), 17 deletions(-)
26
27--- a/sound/usb/card.c
28+++ b/sound/usb/card.c
29@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct u
30 }
31
32 mutex_init(&chip->mutex);
33- mutex_init(&chip->shutdown_mutex);
34+ init_rwsem(&chip->shutdown_rwsem);
35 chip->index = idx;
36 chip->dev = dev;
37 chip->card = card;
38@@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(str
39
40 card = chip->card;
41 mutex_lock(&register_mutex);
42- mutex_lock(&chip->shutdown_mutex);
43+ down_write(&chip->shutdown_rwsem);
44 chip->shutdown = 1;
45 chip->num_interfaces--;
46 if (chip->num_interfaces <= 0) {
47@@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(str
48 snd_usb_mixer_disconnect(p);
49 }
50 usb_chip[chip->index] = NULL;
51- mutex_unlock(&chip->shutdown_mutex);
52+ up_write(&chip->shutdown_rwsem);
53 mutex_unlock(&register_mutex);
54 snd_card_free_when_closed(card);
55 } else {
56- mutex_unlock(&chip->shutdown_mutex);
57+ up_write(&chip->shutdown_rwsem);
58 mutex_unlock(&register_mutex);
59 }
60 }
61@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_au
62 {
63 int err = -ENODEV;
64
65+ down_read(&chip->shutdown_rwsem);
66 if (!chip->shutdown && !chip->probing)
67 err = usb_autopm_get_interface(chip->pm_intf);
68+ up_read(&chip->shutdown_rwsem);
69
70 return err;
71 }
72
73 void snd_usb_autosuspend(struct snd_usb_audio *chip)
74 {
75+ down_read(&chip->shutdown_rwsem);
76 if (!chip->shutdown && !chip->probing)
77 usb_autopm_put_interface(chip->pm_intf);
78+ up_read(&chip->shutdown_rwsem);
79 }
80
81 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
82--- a/sound/usb/mixer.c
83+++ b/sound/usb/mixer.c
84@@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_m
85 err = snd_usb_autoresume(cval->mixer->chip);
86 if (err < 0)
87 return -EIO;
88- mutex_lock(&chip->shutdown_mutex);
89+ down_read(&chip->shutdown_rwsem);
90 while (timeout-- > 0) {
91 if (chip->shutdown)
92 break;
93@@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_m
94 err = -EINVAL;
95
96 out:
97- mutex_unlock(&chip->shutdown_mutex);
98+ up_read(&chip->shutdown_rwsem);
99 snd_usb_autosuspend(cval->mixer->chip);
100 return err;
101 }
102@@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_m
103 if (ret)
104 goto error;
105
106- mutex_lock(&chip->shutdown_mutex);
107+ down_read(&chip->shutdown_rwsem);
108 if (chip->shutdown)
109 ret = -ENODEV;
110 else {
111@@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_m
112 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
113 validx, idx, buf, size);
114 }
115- mutex_unlock(&chip->shutdown_mutex);
116+ up_read(&chip->shutdown_rwsem);
117 snd_usb_autosuspend(chip);
118
119 if (ret < 0) {
120@@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct u
121 err = snd_usb_autoresume(chip);
122 if (err < 0)
123 return -EIO;
124- mutex_lock(&chip->shutdown_mutex);
125+ down_read(&chip->shutdown_rwsem);
126 while (timeout-- > 0) {
127 if (chip->shutdown)
128 break;
129@@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct u
130 err = -EINVAL;
131
132 out:
133- mutex_unlock(&chip->shutdown_mutex);
134+ up_read(&chip->shutdown_rwsem);
135 snd_usb_autosuspend(chip);
136 return err;
137 }
138--- a/sound/usb/pcm.c
139+++ b/sound/usb/pcm.c
140@@ -474,7 +474,7 @@ static int snd_usb_hw_params(struct snd_
141 subs->period_bytes != params_period_bytes(hw_params) ||
142 subs->cur_rate != rate;
143
144- mutex_lock(&subs->stream->chip->shutdown_mutex);
145+ down_read(&subs->stream->chip->shutdown_rwsem);
146 if (subs->stream->chip->shutdown) {
147 ret = -ENODEV;
148 goto unlock;
149@@ -512,7 +512,7 @@ static int snd_usb_hw_params(struct snd_
150 }
151
152 unlock:
153- mutex_unlock(&subs->stream->chip->shutdown_mutex);
154+ up_read(&subs->stream->chip->shutdown_rwsem);
155 return ret;
156 }
157
158@@ -528,12 +528,12 @@ static int snd_usb_hw_free(struct snd_pc
159 subs->cur_audiofmt = NULL;
160 subs->cur_rate = 0;
161 subs->period_bytes = 0;
162- mutex_lock(&subs->stream->chip->shutdown_mutex);
163+ down_read(&subs->stream->chip->shutdown_rwsem);
164 if (!subs->stream->chip->shutdown) {
165 stop_endpoints(subs, 0, 1, 1);
166 deactivate_endpoints(subs);
167 }
168- mutex_unlock(&subs->stream->chip->shutdown_mutex);
169+ up_read(&subs->stream->chip->shutdown_rwsem);
170 return snd_pcm_lib_free_vmalloc_buffer(substream);
171 }
172
173@@ -553,7 +553,7 @@ static int snd_usb_pcm_prepare(struct sn
174 return -ENXIO;
175 }
176
177- mutex_lock(&subs->stream->chip->shutdown_mutex);
178+ down_read(&subs->stream->chip->shutdown_rwsem);
179 if (subs->stream->chip->shutdown) {
180 ret = -ENODEV;
181 goto unlock;
182@@ -582,7 +582,7 @@ static int snd_usb_pcm_prepare(struct sn
183 ret = start_endpoints(subs, 1);
184
185 unlock:
186- mutex_unlock(&subs->stream->chip->shutdown_mutex);
187+ up_read(&subs->stream->chip->shutdown_rwsem);
188 return ret;
189 }
190
191--- a/sound/usb/usbaudio.h
192+++ b/sound/usb/usbaudio.h
193@@ -37,7 +37,7 @@ struct snd_usb_audio {
194 struct usb_interface *pm_intf;
195 u32 usb_id;
196 struct mutex mutex;
197- struct mutex shutdown_mutex;
198+ struct rw_semaphore shutdown_rwsem;
199 unsigned int shutdown:1;
200 unsigned int probing:1;
201 unsigned int autosuspended:1;