diff options
Diffstat (limited to 'sound/usb/misc/ua101.c')
| -rw-r--r-- | sound/usb/misc/ua101.c | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index fb5d68fa7ff..a1bab149df4 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -52,7 +52,7 @@ MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; static unsigned int queue_length = 21; module_param_array(index, int, NULL, 0444); @@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua101_stream *stream) unsigned int i; for (i = 0; i < stream->queue_length; ++i) - usb_kill_urb(&stream->urbs[i]->urb); + if (stream->urbs[i]) + usb_kill_urb(&stream->urbs[i]->urb); } static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index) @@ -484,6 +485,9 @@ static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index) { struct usb_host_interface *alts; + if (!ua->intf[intf_index]) + return; + alts = ua->intf[intf_index]->cur_altsetting; if (alts->desc.bAlternateSetting != 0) { int err = usb_set_interface(ua->dev, @@ -609,14 +613,24 @@ static int start_usb_playback(struct ua101 *ua) static void abort_alsa_capture(struct ua101 *ua) { - if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) + unsigned long flags; + + if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) { + snd_pcm_stream_lock_irqsave(ua->capture.substream, flags); snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags); + } } static void abort_alsa_playback(struct ua101 *ua) { - if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) + unsigned long flags; + + if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) { + snd_pcm_stream_lock_irqsave(ua->playback.substream, flags); snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags); + } } static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, @@ -645,7 +659,7 @@ static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, err = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1500000 / ua->packets_per_second, - 8192000); + UINT_MAX); if (err < 0) return err; err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24); @@ -1116,8 +1130,7 @@ static int alloc_stream_urbs(struct ua101 *ua, struct ua101_stream *stream, usb_init_urb(&urb->urb); urb->urb.dev = ua->dev; urb->urb.pipe = stream->usb_pipe; - urb->urb.transfer_flags = URB_ISO_ASAP | - URB_NO_TRANSFER_DMA_MAP; + urb->urb.transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->urb.transfer_buffer = addr; urb->urb.transfer_dma = dma; urb->urb.transfer_buffer_length = max_packet_size; @@ -1144,27 +1157,37 @@ static void free_stream_urbs(struct ua101_stream *stream) { unsigned int i; - for (i = 0; i < stream->queue_length; ++i) + for (i = 0; i < stream->queue_length; ++i) { kfree(stream->urbs[i]); + stream->urbs[i] = NULL; + } } static void free_usb_related_resources(struct ua101 *ua, struct usb_interface *interface) { unsigned int i; + struct usb_interface *intf; + mutex_lock(&ua->mutex); free_stream_urbs(&ua->capture); free_stream_urbs(&ua->playback); + mutex_unlock(&ua->mutex); free_stream_buffers(ua, &ua->capture); free_stream_buffers(ua, &ua->playback); - for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) - if (ua->intf[i]) { - usb_set_intfdata(ua->intf[i], NULL); - if (ua->intf[i] != interface) + for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) { + mutex_lock(&ua->mutex); + intf = ua->intf[i]; + ua->intf[i] = NULL; + mutex_unlock(&ua->mutex); + if (intf) { + usb_set_intfdata(intf, NULL); + if (intf != interface) usb_driver_release_interface(&ua101_driver, - ua->intf[i]); + intf); } + } } static void ua101_card_free(struct snd_card *card) @@ -1220,8 +1243,9 @@ static int ua101_probe(struct usb_interface *interface, mutex_unlock(&devices_mutex); return -ENOENT; } - err = snd_card_create(index[card_index], id[card_index], THIS_MODULE, - sizeof(*ua), &card); + err = snd_card_new(&interface->dev, + index[card_index], id[card_index], THIS_MODULE, + sizeof(*ua), &card); if (err < 0) { mutex_unlock(&devices_mutex); return err; @@ -1260,8 +1284,6 @@ static int ua101_probe(struct usb_interface *interface, } } - snd_card_set_dev(card, &interface->dev); - err = detect_usb_format(ua); if (err < 0) goto probe_error; @@ -1336,7 +1358,7 @@ static void ua101_disconnect(struct usb_interface *interface) snd_card_disconnect(ua->card); /* make sure that there are no pending USB requests */ - __list_for_each(midi, &ua->midi_list) + list_for_each(midi, &ua->midi_list) snd_usbmidi_disconnect(midi); abort_alsa_playback(ua); abort_alsa_capture(ua); @@ -1373,16 +1395,4 @@ static struct usb_driver ua101_driver = { #endif }; -static int __init alsa_card_ua101_init(void) -{ - return usb_register(&ua101_driver); -} - -static void __exit alsa_card_ua101_exit(void) -{ - usb_deregister(&ua101_driver); - mutex_destroy(&devices_mutex); -} - -module_init(alsa_card_ua101_init); -module_exit(alsa_card_ua101_exit); +module_usb_driver(ua101_driver); |
