summaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2016-03-30 19:47:05 -0400
committerTakashi Iwai <tiwai@suse.de>2016-03-31 09:36:18 -0400
commit04a2c73c97ebb224dfb411ab35bb18d7b8245e39 (patch)
treed671f334a88b4f9d2eceb1ba3af7cb4370a1cbae /sound/firewire
parent923f92ebb43e7a09915a5708d4805c1e099db46c (diff)
ALSA: bebob: delayed registration of sound card
Some bebob based units tends to fail asynchronous communication when IEEE 1394 bus is under bus-reset state. When registering sound card instance at unit probe callback, userspace applications can be involved to the state. This commit postpones the registration till the bus is calm. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/bebob/bebob.c215
-rw-r--r--sound/firewire/bebob/bebob.h5
2 files changed, 131 insertions, 89 deletions
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index 932901de255f..f7e2cbd2a313 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -126,6 +126,17 @@ end:
126 return err; 126 return err;
127} 127}
128 128
129static void bebob_free(struct snd_bebob *bebob)
130{
131 snd_bebob_stream_destroy_duplex(bebob);
132 fw_unit_put(bebob->unit);
133
134 kfree(bebob->maudio_special_quirk);
135
136 mutex_destroy(&bebob->mutex);
137 kfree(bebob);
138}
139
129/* 140/*
130 * This module releases the FireWire unit data after all ALSA character devices 141 * This module releases the FireWire unit data after all ALSA character devices
131 * are released by applications. This is for releasing stream data or finishing 142 * are released by applications. This is for releasing stream data or finishing
@@ -137,18 +148,11 @@ bebob_card_free(struct snd_card *card)
137{ 148{
138 struct snd_bebob *bebob = card->private_data; 149 struct snd_bebob *bebob = card->private_data;
139 150
140 snd_bebob_stream_destroy_duplex(bebob); 151 mutex_lock(&devices_mutex);
141 fw_unit_put(bebob->unit); 152 clear_bit(bebob->card_index, devices_used);
142 153 mutex_unlock(&devices_mutex);
143 kfree(bebob->maudio_special_quirk);
144
145 if (bebob->card_index >= 0) {
146 mutex_lock(&devices_mutex);
147 clear_bit(bebob->card_index, devices_used);
148 mutex_unlock(&devices_mutex);
149 }
150 154
151 mutex_destroy(&bebob->mutex); 155 bebob_free(card->private_data);
152} 156}
153 157
154static const struct snd_bebob_spec * 158static const struct snd_bebob_spec *
@@ -176,16 +180,17 @@ check_audiophile_booted(struct fw_unit *unit)
176 return strncmp(name, "FW Audiophile Bootloader", 15) != 0; 180 return strncmp(name, "FW Audiophile Bootloader", 15) != 0;
177} 181}
178 182
179static int 183static void
180bebob_probe(struct fw_unit *unit, 184do_registration(struct work_struct *work)
181 const struct ieee1394_device_id *entry)
182{ 185{
183 struct snd_card *card; 186 struct snd_bebob *bebob =
184 struct snd_bebob *bebob; 187 container_of(work, struct snd_bebob, dwork.work);
185 const struct snd_bebob_spec *spec;
186 unsigned int card_index; 188 unsigned int card_index;
187 int err; 189 int err;
188 190
191 if (bebob->registered)
192 return;
193
189 mutex_lock(&devices_mutex); 194 mutex_lock(&devices_mutex);
190 195
191 for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { 196 for (card_index = 0; card_index < SNDRV_CARDS; card_index++) {
@@ -193,64 +198,39 @@ bebob_probe(struct fw_unit *unit,
193 break; 198 break;
194 } 199 }
195 if (card_index >= SNDRV_CARDS) { 200 if (card_index >= SNDRV_CARDS) {
196 err = -ENOENT; 201 mutex_unlock(&devices_mutex);
197 goto end; 202 return;
198 } 203 }
199 204
200 if ((entry->vendor_id == VEN_FOCUSRITE) && 205 err = snd_card_new(&bebob->unit->device, index[card_index],
201 (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) 206 id[card_index], THIS_MODULE, 0, &bebob->card);
202 spec = get_saffire_spec(unit); 207 if (err < 0) {
203 else if ((entry->vendor_id == VEN_MAUDIO1) && 208 mutex_unlock(&devices_mutex);
204 (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && 209 return;
205 !check_audiophile_booted(unit))
206 spec = NULL;
207 else
208 spec = (const struct snd_bebob_spec *)entry->driver_data;
209
210 if (spec == NULL) {
211 if ((entry->vendor_id == VEN_MAUDIO1) ||
212 (entry->vendor_id == VEN_MAUDIO2))
213 err = snd_bebob_maudio_load_firmware(unit);
214 else
215 err = -ENOSYS;
216 goto end;
217 } 210 }
218 211
219 err = snd_card_new(&unit->device, index[card_index], id[card_index],
220 THIS_MODULE, sizeof(struct snd_bebob), &card);
221 if (err < 0)
222 goto end;
223 bebob = card->private_data;
224 bebob->card_index = card_index;
225 set_bit(card_index, devices_used);
226 card->private_free = bebob_card_free;
227
228 bebob->card = card;
229 bebob->unit = fw_unit_get(unit);
230 bebob->spec = spec;
231 mutex_init(&bebob->mutex);
232 spin_lock_init(&bebob->lock);
233 init_waitqueue_head(&bebob->hwdep_wait);
234
235 err = name_device(bebob); 212 err = name_device(bebob);
236 if (err < 0) 213 if (err < 0)
237 goto error; 214 goto error;
238 215
239 if ((entry->vendor_id == VEN_MAUDIO1) && 216 if (bebob->spec == &maudio_special_spec) {
240 (entry->model_id == MODEL_MAUDIO_FW1814)) 217 if (bebob->entry->model_id == MODEL_MAUDIO_FW1814)
241 err = snd_bebob_maudio_special_discover(bebob, true); 218 err = snd_bebob_maudio_special_discover(bebob, true);
242 else if ((entry->vendor_id == VEN_MAUDIO1) && 219 else
243 (entry->model_id == MODEL_MAUDIO_PROJECTMIX)) 220 err = snd_bebob_maudio_special_discover(bebob, false);
244 err = snd_bebob_maudio_special_discover(bebob, false); 221 } else {
245 else
246 err = snd_bebob_stream_discover(bebob); 222 err = snd_bebob_stream_discover(bebob);
223 }
224 if (err < 0)
225 goto error;
226
227 err = snd_bebob_stream_init_duplex(bebob);
247 if (err < 0) 228 if (err < 0)
248 goto error; 229 goto error;
249 230
250 snd_bebob_proc_init(bebob); 231 snd_bebob_proc_init(bebob);
251 232
252 if ((bebob->midi_input_ports > 0) || 233 if (bebob->midi_input_ports > 0 || bebob->midi_output_ports > 0) {
253 (bebob->midi_output_ports > 0)) {
254 err = snd_bebob_create_midi_devices(bebob); 234 err = snd_bebob_create_midi_devices(bebob);
255 if (err < 0) 235 if (err < 0)
256 goto error; 236 goto error;
@@ -264,16 +244,75 @@ bebob_probe(struct fw_unit *unit,
264 if (err < 0) 244 if (err < 0)
265 goto error; 245 goto error;
266 246
267 err = snd_bebob_stream_init_duplex(bebob); 247 err = snd_card_register(bebob->card);
268 if (err < 0) 248 if (err < 0)
269 goto error; 249 goto error;
270 250
271 if (!bebob->maudio_special_quirk) { 251 set_bit(card_index, devices_used);
272 err = snd_card_register(card); 252 mutex_unlock(&devices_mutex);
273 if (err < 0) { 253
274 snd_bebob_stream_destroy_duplex(bebob); 254 /*
275 goto error; 255 * After registered, bebob instance can be released corresponding to
276 } 256 * releasing the sound card instance.
257 */
258 bebob->card->private_free = bebob_card_free;
259 bebob->card->private_data = bebob;
260 bebob->registered = true;
261
262 return;
263error:
264 mutex_unlock(&devices_mutex);
265 snd_bebob_stream_destroy_duplex(bebob);
266 snd_card_free(bebob->card);
267 dev_info(&bebob->unit->device,
268 "Sound card registration failed: %d\n", err);
269}
270
271static int
272bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
273{
274 struct snd_bebob *bebob;
275 const struct snd_bebob_spec *spec;
276
277 if (entry->vendor_id == VEN_FOCUSRITE &&
278 entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)
279 spec = get_saffire_spec(unit);
280 else if (entry->vendor_id == VEN_MAUDIO1 &&
281 entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH &&
282 !check_audiophile_booted(unit))
283 spec = NULL;
284 else
285 spec = (const struct snd_bebob_spec *)entry->driver_data;
286
287 if (spec == NULL) {
288 if (entry->vendor_id == VEN_MAUDIO1 ||
289 entry->vendor_id == VEN_MAUDIO2)
290 return snd_bebob_maudio_load_firmware(unit);
291 else
292 return -ENODEV;
293 }
294
295 /* Allocate this independent of sound card instance. */
296 bebob = kzalloc(sizeof(struct snd_bebob), GFP_KERNEL);
297 if (bebob == NULL)
298 return -ENOMEM;
299
300 bebob->unit = fw_unit_get(unit);
301 bebob->entry = entry;
302 bebob->spec = spec;
303 dev_set_drvdata(&unit->device, bebob);
304
305 mutex_init(&bebob->mutex);
306 spin_lock_init(&bebob->lock);
307 init_waitqueue_head(&bebob->hwdep_wait);
308
309 /* Allocate and register this sound card later. */
310 INIT_DEFERRABLE_WORK(&bebob->dwork, do_registration);
311
312 if (entry->vendor_id != VEN_MAUDIO1 ||
313 (entry->model_id != MODEL_MAUDIO_FW1814 &&
314 entry->model_id != MODEL_MAUDIO_PROJECTMIX)) {
315 snd_fw_schedule_registration(unit, &bebob->dwork);
277 } else { 316 } else {
278 /* 317 /*
279 * This is a workaround. This bus reset seems to have an effect 318 * This is a workaround. This bus reset seems to have an effect
@@ -285,19 +324,11 @@ bebob_probe(struct fw_unit *unit,
285 * signals from dbus and starts I/Os. To avoid I/Os till the 324 * signals from dbus and starts I/Os. To avoid I/Os till the
286 * future bus reset, registration is done in next update(). 325 * future bus reset, registration is done in next update().
287 */ 326 */
288 bebob->deferred_registration = true;
289 fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, 327 fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card,
290 false, true); 328 false, true);
291 } 329 }
292 330
293 dev_set_drvdata(&unit->device, bebob); 331 return 0;
294end:
295 mutex_unlock(&devices_mutex);
296 return err;
297error:
298 mutex_unlock(&devices_mutex);
299 snd_card_free(card);
300 return err;
301} 332}
302 333
303/* 334/*
@@ -324,15 +355,11 @@ bebob_update(struct fw_unit *unit)
324 if (bebob == NULL) 355 if (bebob == NULL)
325 return; 356 return;
326 357
327 fcp_bus_reset(bebob->unit); 358 /* Postpone a workqueue for deferred registration. */
328 359 if (!bebob->registered)
329 if (bebob->deferred_registration) { 360 snd_fw_schedule_registration(unit, &bebob->dwork);
330 if (snd_card_register(bebob->card) < 0) { 361 else
331 snd_bebob_stream_destroy_duplex(bebob); 362 fcp_bus_reset(bebob->unit);
332 snd_card_free(bebob->card);
333 }
334 bebob->deferred_registration = false;
335 }
336} 363}
337 364
338static void bebob_remove(struct fw_unit *unit) 365static void bebob_remove(struct fw_unit *unit)
@@ -342,8 +369,20 @@ static void bebob_remove(struct fw_unit *unit)
342 if (bebob == NULL) 369 if (bebob == NULL)
343 return; 370 return;
344 371
345 /* No need to wait for releasing card object in this context. */ 372 /*
346 snd_card_free_when_closed(bebob->card); 373 * Confirm to stop the work for registration before the sound card is
374 * going to be released. The work is not scheduled again because bus
375 * reset handler is not called anymore.
376 */
377 cancel_delayed_work_sync(&bebob->dwork);
378
379 if (bebob->registered) {
380 /* No need to wait for releasing card object in this context. */
381 snd_card_free_when_closed(bebob->card);
382 } else {
383 /* Don't forget this case. */
384 bebob_free(bebob);
385 }
347} 386}
348 387
349static const struct snd_bebob_rate_spec normal_rate_spec = { 388static const struct snd_bebob_rate_spec normal_rate_spec = {
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index b50bb33d9d46..2a442a7a2119 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -83,6 +83,10 @@ struct snd_bebob {
83 struct mutex mutex; 83 struct mutex mutex;
84 spinlock_t lock; 84 spinlock_t lock;
85 85
86 bool registered;
87 struct delayed_work dwork;
88
89 const struct ieee1394_device_id *entry;
86 const struct snd_bebob_spec *spec; 90 const struct snd_bebob_spec *spec;
87 91
88 unsigned int midi_input_ports; 92 unsigned int midi_input_ports;
@@ -111,7 +115,6 @@ struct snd_bebob {
111 115
112 /* for M-Audio special devices */ 116 /* for M-Audio special devices */
113 void *maudio_special_quirk; 117 void *maudio_special_quirk;
114 bool deferred_registration;
115 118
116 /* For BeBoB version quirk. */ 119 /* For BeBoB version quirk. */
117 unsigned int version; 120 unsigned int version;