aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r--sound/core/pcm.c84
1 files changed, 56 insertions, 28 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index ece25c718e95..192a433a2403 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device);
42static int snd_pcm_dev_register(struct snd_device *device); 42static int snd_pcm_dev_register(struct snd_device *device);
43static int snd_pcm_dev_disconnect(struct snd_device *device); 43static int snd_pcm_dev_disconnect(struct snd_device *device);
44 44
45static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) 45static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
46{ 46{
47 struct snd_pcm *pcm; 47 struct snd_pcm *pcm;
48 48
@@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
53 return NULL; 53 return NULL;
54} 54}
55 55
56static int snd_pcm_next(struct snd_card *card, int device)
57{
58 struct snd_pcm *pcm;
59
60 list_for_each_entry(pcm, &snd_pcm_devices, list) {
61 if (pcm->card == card && pcm->device > device)
62 return pcm->device;
63 else if (pcm->card->number > card->number)
64 return -1;
65 }
66 return -1;
67}
68
69static int snd_pcm_add(struct snd_pcm *newpcm)
70{
71 struct snd_pcm *pcm;
72
73 list_for_each_entry(pcm, &snd_pcm_devices, list) {
74 if (pcm->card == newpcm->card && pcm->device == newpcm->device)
75 return -EBUSY;
76 if (pcm->card->number > newpcm->card->number ||
77 (pcm->card == newpcm->card &&
78 pcm->device > newpcm->device)) {
79 list_add(&newpcm->list, pcm->list.prev);
80 return 0;
81 }
82 }
83 list_add_tail(&newpcm->list, &snd_pcm_devices);
84 return 0;
85}
86
56static int snd_pcm_control_ioctl(struct snd_card *card, 87static int snd_pcm_control_ioctl(struct snd_card *card,
57 struct snd_ctl_file *control, 88 struct snd_ctl_file *control,
58 unsigned int cmd, unsigned long arg) 89 unsigned int cmd, unsigned long arg)
@@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
65 if (get_user(device, (int __user *)arg)) 96 if (get_user(device, (int __user *)arg))
66 return -EFAULT; 97 return -EFAULT;
67 mutex_lock(&register_mutex); 98 mutex_lock(&register_mutex);
68 device = device < 0 ? 0 : device + 1; 99 device = snd_pcm_next(card, device);
69 while (device < SNDRV_PCM_DEVICES) {
70 if (snd_pcm_search(card, device))
71 break;
72 device++;
73 }
74 if (device == SNDRV_PCM_DEVICES)
75 device = -1;
76 mutex_unlock(&register_mutex); 100 mutex_unlock(&register_mutex);
77 if (put_user(device, (int __user *)arg)) 101 if (put_user(device, (int __user *)arg))
78 return -EFAULT; 102 return -EFAULT;
@@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
98 if (get_user(subdevice, &info->subdevice)) 122 if (get_user(subdevice, &info->subdevice))
99 return -EFAULT; 123 return -EFAULT;
100 mutex_lock(&register_mutex); 124 mutex_lock(&register_mutex);
101 pcm = snd_pcm_search(card, device); 125 pcm = snd_pcm_get(card, device);
102 if (pcm == NULL) { 126 if (pcm == NULL) {
103 err = -ENXIO; 127 err = -ENXIO;
104 goto _error; 128 goto _error;
@@ -232,7 +256,6 @@ static char *snd_pcm_tstamp_mode_names[] = {
232 256
233static const char *snd_pcm_stream_name(int stream) 257static const char *snd_pcm_stream_name(int stream)
234{ 258{
235 snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL);
236 return snd_pcm_stream_names[stream]; 259 return snd_pcm_stream_names[stream];
237} 260}
238 261
@@ -248,7 +271,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
248 271
249static const char *snd_pcm_tstamp_mode_name(int mode) 272static const char *snd_pcm_tstamp_mode_name(int mode)
250{ 273{
251 snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL);
252 return snd_pcm_tstamp_mode_names[mode]; 274 return snd_pcm_tstamp_mode_names[mode];
253} 275}
254 276
@@ -682,9 +704,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
682 .dev_disconnect = snd_pcm_dev_disconnect, 704 .dev_disconnect = snd_pcm_dev_disconnect,
683 }; 705 };
684 706
685 snd_assert(rpcm != NULL, return -EINVAL); 707 if (snd_BUG_ON(!card))
686 *rpcm = NULL; 708 return -ENXIO;
687 snd_assert(card != NULL, return -ENXIO); 709 if (rpcm)
710 *rpcm = NULL;
688 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); 711 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
689 if (pcm == NULL) { 712 if (pcm == NULL) {
690 snd_printk(KERN_ERR "Cannot allocate PCM\n"); 713 snd_printk(KERN_ERR "Cannot allocate PCM\n");
@@ -708,7 +731,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
708 snd_pcm_free(pcm); 731 snd_pcm_free(pcm);
709 return err; 732 return err;
710 } 733 }
711 *rpcm = pcm; 734 if (rpcm)
735 *rpcm = pcm;
712 return 0; 736 return 0;
713} 737}
714 738
@@ -742,7 +766,8 @@ static int snd_pcm_free(struct snd_pcm *pcm)
742{ 766{
743 struct snd_pcm_notify *notify; 767 struct snd_pcm_notify *notify;
744 768
745 snd_assert(pcm != NULL, return -ENXIO); 769 if (!pcm)
770 return 0;
746 list_for_each_entry(notify, &snd_pcm_notify_list, list) { 771 list_for_each_entry(notify, &snd_pcm_notify_list, list) {
747 notify->n_unregister(pcm); 772 notify->n_unregister(pcm);
748 } 773 }
@@ -773,9 +798,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
773 int prefer_subdevice = -1; 798 int prefer_subdevice = -1;
774 size_t size; 799 size_t size;
775 800
776 snd_assert(rsubstream != NULL, return -EINVAL); 801 if (snd_BUG_ON(!pcm || !rsubstream))
802 return -ENXIO;
777 *rsubstream = NULL; 803 *rsubstream = NULL;
778 snd_assert(pcm != NULL, return -ENXIO);
779 pstr = &pcm->streams[stream]; 804 pstr = &pcm->streams[stream];
780 if (pstr->substream == NULL || pstr->substream_count == 0) 805 if (pstr->substream == NULL || pstr->substream_count == 0)
781 return -ENODEV; 806 return -ENODEV;
@@ -883,8 +908,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
883{ 908{
884 struct snd_pcm_runtime *runtime; 909 struct snd_pcm_runtime *runtime;
885 910
911 if (PCM_RUNTIME_CHECK(substream))
912 return;
886 runtime = substream->runtime; 913 runtime = substream->runtime;
887 snd_assert(runtime != NULL, return);
888 if (runtime->private_free != NULL) 914 if (runtime->private_free != NULL)
889 runtime->private_free(runtime); 915 runtime->private_free(runtime);
890 snd_free_pages((void*)runtime->status, 916 snd_free_pages((void*)runtime->status,
@@ -929,13 +955,14 @@ static int snd_pcm_dev_register(struct snd_device *device)
929 struct snd_pcm *pcm = device->device_data; 955 struct snd_pcm *pcm = device->device_data;
930 struct device *dev; 956 struct device *dev;
931 957
932 snd_assert(pcm != NULL && device != NULL, return -ENXIO); 958 if (snd_BUG_ON(!pcm || !device))
959 return -ENXIO;
933 mutex_lock(&register_mutex); 960 mutex_lock(&register_mutex);
934 if (snd_pcm_search(pcm->card, pcm->device)) { 961 err = snd_pcm_add(pcm);
962 if (err) {
935 mutex_unlock(&register_mutex); 963 mutex_unlock(&register_mutex);
936 return -EBUSY; 964 return err;
937 } 965 }
938 list_add_tail(&pcm->list, &snd_pcm_devices);
939 for (cidx = 0; cidx < 2; cidx++) { 966 for (cidx = 0; cidx < 2; cidx++) {
940 int devtype = -1; 967 int devtype = -1;
941 if (pcm->streams[cidx].substream == NULL) 968 if (pcm->streams[cidx].substream == NULL)
@@ -1019,10 +1046,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1019{ 1046{
1020 struct snd_pcm *pcm; 1047 struct snd_pcm *pcm;
1021 1048
1022 snd_assert(notify != NULL && 1049 if (snd_BUG_ON(!notify ||
1023 notify->n_register != NULL && 1050 !notify->n_register ||
1024 notify->n_unregister != NULL && 1051 !notify->n_unregister ||
1025 notify->n_disconnect, return -EINVAL); 1052 !notify->n_disconnect))
1053 return -EINVAL;
1026 mutex_lock(&register_mutex); 1054 mutex_lock(&register_mutex);
1027 if (nfree) { 1055 if (nfree) {
1028 list_del(&notify->list); 1056 list_del(&notify->list);