aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usx2y/usbusx2yaudio.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-02-14 03:05:47 -0500
committerTakashi Iwai <tiwai@suse.de>2014-02-17 04:16:25 -0500
commite2439a5401486d8b7f1076fc6df9b80143ed62e2 (patch)
tree3dd69d1751290ac803fe9014db2746523eaac058 /sound/usb/usx2y/usbusx2yaudio.c
parent1f85a0f0cce583a8ac436bda8807ec8fd8e8ef16 (diff)
ALSA: usx2y: Don't peep the card internal object
Avoid traversing the device object list of the card instance just for checking the PCM streams. The driver's private object already contains the array of substream pointers, so it can be simply looked through. The card internal may be restructured in future, thus better not to rely on it. Also, this fixes the possible deadlocks in PCM mutex. Instead of taking multiple PCM mutexes, just take the common mutex in all places. Along with it, rename prepare_mutex as pcm_mutex. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/usx2y/usbusx2yaudio.c')
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 6234a51625b1..a63330dd1407 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -752,36 +752,44 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream,
752 unsigned int rate = params_rate(hw_params); 752 unsigned int rate = params_rate(hw_params);
753 snd_pcm_format_t format = params_format(hw_params); 753 snd_pcm_format_t format = params_format(hw_params);
754 struct snd_card *card = substream->pstr->pcm->card; 754 struct snd_card *card = substream->pstr->pcm->card;
755 struct list_head *list; 755 struct usX2Ydev *dev = usX2Y(card);
756 int i;
756 757
758 mutex_lock(&usX2Y(card)->pcm_mutex);
757 snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); 759 snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
758 // all pcm substreams off one usX2Y have to operate at the same rate & format 760 /* all pcm substreams off one usX2Y have to operate at the same
759 list_for_each(list, &card->devices) { 761 * rate & format
760 struct snd_device *dev; 762 */
761 struct snd_pcm *pcm; 763 for (i = 0; i < dev->pcm_devs * 2; i++) {
762 int s; 764 struct snd_usX2Y_substream *subs = dev->subs[i];
763 dev = snd_device(list); 765 struct snd_pcm_substream *test_substream;
764 if (dev->type != SNDRV_DEV_PCM) 766
767 if (!subs)
768 continue;
769 test_substream = subs->pcm_substream;
770 if (!test_substream || test_substream == substream ||
771 !test_substream->runtime)
765 continue; 772 continue;
766 pcm = dev->device_data; 773 if ((test_substream->runtime->format &&
767 for (s = 0; s < 2; ++s) { 774 test_substream->runtime->format != format) ||
768 struct snd_pcm_substream *test_substream; 775 (test_substream->runtime->rate &&
769 test_substream = pcm->streams[s].substream; 776 test_substream->runtime->rate != rate)) {
770 if (test_substream && test_substream != substream && 777 err = -EINVAL;
771 test_substream->runtime && 778 goto error;
772 ((test_substream->runtime->format &&
773 test_substream->runtime->format != format) ||
774 (test_substream->runtime->rate &&
775 test_substream->runtime->rate != rate)))
776 return -EINVAL;
777 } 779 }
778 } 780 }
779 if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { 781
782 err = snd_pcm_lib_malloc_pages(substream,
783 params_buffer_bytes(hw_params));
784 if (err < 0) {
780 snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", 785 snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n",
781 substream, params_buffer_bytes(hw_params), err); 786 substream, params_buffer_bytes(hw_params), err);
782 return err; 787 goto error;
783 } 788 }
784 return 0; 789
790 error:
791 mutex_unlock(&usX2Y(card)->pcm_mutex);
792 return err;
785} 793}
786 794
787/* 795/*
@@ -791,7 +799,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
791{ 799{
792 struct snd_pcm_runtime *runtime = substream->runtime; 800 struct snd_pcm_runtime *runtime = substream->runtime;
793 struct snd_usX2Y_substream *subs = runtime->private_data; 801 struct snd_usX2Y_substream *subs = runtime->private_data;
794 mutex_lock(&subs->usX2Y->prepare_mutex); 802 mutex_lock(&subs->usX2Y->pcm_mutex);
795 snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); 803 snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
796 804
797 if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { 805 if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
@@ -812,7 +820,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
812 usX2Y_urbs_release(subs); 820 usX2Y_urbs_release(subs);
813 } 821 }
814 } 822 }
815 mutex_unlock(&subs->usX2Y->prepare_mutex); 823 mutex_unlock(&subs->usX2Y->pcm_mutex);
816 return snd_pcm_lib_free_pages(substream); 824 return snd_pcm_lib_free_pages(substream);
817} 825}
818/* 826/*
@@ -829,7 +837,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
829 int err = 0; 837 int err = 0;
830 snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); 838 snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
831 839
832 mutex_lock(&usX2Y->prepare_mutex); 840 mutex_lock(&usX2Y->pcm_mutex);
833 usX2Y_subs_prepare(subs); 841 usX2Y_subs_prepare(subs);
834// Start hardware streams 842// Start hardware streams
835// SyncStream first.... 843// SyncStream first....
@@ -849,7 +857,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
849 err = usX2Y_urbs_start(subs); 857 err = usX2Y_urbs_start(subs);
850 858
851 up_prepare_mutex: 859 up_prepare_mutex:
852 mutex_unlock(&usX2Y->prepare_mutex); 860 mutex_unlock(&usX2Y->pcm_mutex);
853 return err; 861 return err;
854} 862}
855 863