static void do_registration(struct work_struct *work) { struct snd_bebob *bebob = container_of(work, struct snd_bebob, dwork.work); unsigned int card_index; int err; if (bebob->registered) return; mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { if (!test_bit(card_index, devices_used) && enable[card_index]) break; } if (card_index >= SNDRV_CARDS) { mutex_unlock(&devices_mutex); return; } err = snd_card_new(&bebob->unit->device, index[card_index], id[card_index], THIS_MODULE, 0, &bebob->card); if (err < 0) { mutex_unlock(&devices_mutex); return; } err = name_device(bebob); if (err < 0) goto error; if (bebob->spec == &maudio_special_spec) { if (bebob->entry->model_id == MODEL_MAUDIO_FW1814) err = snd_bebob_maudio_special_discover(bebob, true); else err = snd_bebob_maudio_special_discover(bebob, false); } else { err = snd_bebob_stream_discover(bebob); } if (err < 0) goto error; err = snd_bebob_stream_init_duplex(bebob); if (err < 0) goto error; snd_bebob_proc_init(bebob); if (bebob->midi_input_ports > 0 || bebob->midi_output_ports > 0) { err = snd_bebob_create_midi_devices(bebob); if (err < 0) goto error; } err = snd_bebob_create_pcm_devices(bebob); if (err < 0) goto error; err = snd_bebob_create_hwdep_device(bebob); if (err < 0) goto error; err = snd_card_register(bebob->card); if (err < 0) goto error; set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); /* * After registered, bebob instance can be released corresponding to * releasing the sound card instance. */ bebob->card->private_free = bebob_card_free; bebob->card->private_data = bebob; bebob->registered = true; return; error: mutex_unlock(&devices_mutex); snd_bebob_stream_destroy_duplex(bebob); snd_card_free(bebob->card); dev_info(&bebob->unit->device, "Sound card registration failed: %d\n", err); }
static int bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { struct snd_card *card; struct snd_bebob *bebob; const struct snd_bebob_spec *spec; unsigned int card_index; int err; mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { if (!test_bit(card_index, devices_used) && enable[card_index]) break; } if (card_index >= SNDRV_CARDS) { err = -ENOENT; goto end; } if ((entry->vendor_id == VEN_FOCUSRITE) && (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) spec = get_saffire_spec(unit); else if ((entry->vendor_id == VEN_MAUDIO1) && (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && !check_audiophile_booted(unit)) spec = NULL; else spec = (const struct snd_bebob_spec *)entry->driver_data; if (spec == NULL) { if ((entry->vendor_id == VEN_MAUDIO1) || (entry->vendor_id == VEN_MAUDIO2)) err = snd_bebob_maudio_load_firmware(unit); else err = -ENOSYS; goto end; } err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, sizeof(struct snd_bebob), &card); if (err < 0) goto end; bebob = card->private_data; bebob->card_index = card_index; set_bit(card_index, devices_used); card->private_free = bebob_card_free; bebob->card = card; bebob->unit = fw_unit_get(unit); bebob->spec = spec; mutex_init(&bebob->mutex); spin_lock_init(&bebob->lock); init_waitqueue_head(&bebob->hwdep_wait); err = name_device(bebob, entry->vendor_id); if (err < 0) goto error; if ((entry->vendor_id == VEN_MAUDIO1) && (entry->model_id == MODEL_MAUDIO_FW1814)) err = snd_bebob_maudio_special_discover(bebob, true); else if ((entry->vendor_id == VEN_MAUDIO1) && (entry->model_id == MODEL_MAUDIO_PROJECTMIX)) err = snd_bebob_maudio_special_discover(bebob, false); else err = snd_bebob_stream_discover(bebob); if (err < 0) goto error; snd_bebob_proc_init(bebob); if ((bebob->midi_input_ports > 0) || (bebob->midi_output_ports > 0)) { err = snd_bebob_create_midi_devices(bebob); if (err < 0) goto error; } err = snd_bebob_create_pcm_devices(bebob); if (err < 0) goto error; err = snd_bebob_create_hwdep_device(bebob); if (err < 0) goto error; err = snd_bebob_stream_init_duplex(bebob); if (err < 0) goto error; if (!bebob->maudio_special_quirk) { err = snd_card_register(card); if (err < 0) { snd_bebob_stream_destroy_duplex(bebob); goto error; } } else { /* * This is a workaround. This bus reset seems to have an effect * to make devices correctly handling transactions. Without * this, the devices have gap_count mismatch. This causes much * failure of transaction. * * Just after registration, user-land application receive * signals from dbus and starts I/Os. To avoid I/Os till the * future bus reset, registration is done in next update(). */ bebob->deferred_registration = true; fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, false, true); } dev_set_drvdata(&unit->device, bebob); end: mutex_unlock(&devices_mutex); return err; error: mutex_unlock(&devices_mutex); snd_card_free(card); return err; }