diff options
Diffstat (limited to 'sound/usb/misc')
| -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);  | 
