aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorPawel MOLL <pawel.moll@st.com>2008-07-29 12:34:26 -0400
committerJaroslav Kysela <perex@perex.cz>2008-07-29 15:32:48 -0400
commit9423969005586e6e27ca380e01b4a8c50698e2af (patch)
tree818bef3892109c05a4ad5ec3ae5e90dd4436c0c6 /sound
parent815ecf8dec95d07e260a16ebe8409f4b7c0fdc0f (diff)
ALSA: Fix limit of 8 PCM devices in SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE
When compiled with CONFIG_SND_DYNAMIC_MINORS the ALSA core is fine to have more than 8 PCM devices per card, except one place - the SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE ioctl, which will not enumerate devices > 7. This patch fixes the issue, changing the devices list organisation. Instead of adding new device to the tail, the list is now kept always ordered (by card number, then device number). Thus, during enumeration, it is easy to discover the fact that there is no more given card's devices. The same limit was present in OSS emulation code. It has been fixed as well. Additionally the device field of struct snd_pcm is now int, instead of unsigned int, as there is no obvious reason for keeping it unsigned. This caused a lot of problems with comparing this value with other (almost always signed) variables. There is just one more place where device number is unsigned - in struct snd_pcm_info, which should be also sorted out in future. Signed-off-by: Pawel MOLL <pawel.moll@st.com> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/oss/pcm_oss.c10
-rw-r--r--sound/core/pcm.c50
-rw-r--r--sound/core/sound.c2
3 files changed, 42 insertions, 20 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 4c601b192ddf..4ccd761a5f41 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2947,7 +2947,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index)
2947static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) 2947static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
2948{ 2948{
2949 pcm->oss.reg = 0; 2949 pcm->oss.reg = 0;
2950 if (dsp_map[pcm->card->number] == (int)pcm->device) { 2950 if (dsp_map[pcm->card->number] == pcm->device) {
2951 char name[128]; 2951 char name[128];
2952 int duplex; 2952 int duplex;
2953 register_oss_dsp(pcm, 0); 2953 register_oss_dsp(pcm, 0);
@@ -2963,7 +2963,7 @@ static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
2963 pcm->oss.reg++; 2963 pcm->oss.reg++;
2964 pcm->oss.reg_mask |= 1; 2964 pcm->oss.reg_mask |= 1;
2965 } 2965 }
2966 if (adsp_map[pcm->card->number] == (int)pcm->device) { 2966 if (adsp_map[pcm->card->number] == pcm->device) {
2967 register_oss_dsp(pcm, 1); 2967 register_oss_dsp(pcm, 1);
2968 pcm->oss.reg++; 2968 pcm->oss.reg++;
2969 pcm->oss.reg_mask |= 2; 2969 pcm->oss.reg_mask |= 2;
@@ -2988,7 +2988,7 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
2988 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2988 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2989 pcm->card, 1); 2989 pcm->card, 1);
2990 } 2990 }
2991 if (dsp_map[pcm->card->number] == (int)pcm->device) { 2991 if (dsp_map[pcm->card->number] == pcm->device) {
2992#ifdef SNDRV_OSS_INFO_DEV_AUDIO 2992#ifdef SNDRV_OSS_INFO_DEV_AUDIO
2993 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); 2993 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
2994#endif 2994#endif
@@ -3019,12 +3019,12 @@ static int __init alsa_pcm_oss_init(void)
3019 3019
3020 /* check device map table */ 3020 /* check device map table */
3021 for (i = 0; i < SNDRV_CARDS; i++) { 3021 for (i = 0; i < SNDRV_CARDS; i++) {
3022 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { 3022 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_OS_MINORS) {
3023 snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", 3023 snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n",
3024 i, dsp_map[i]); 3024 i, dsp_map[i]);
3025 dsp_map[i] = 0; 3025 dsp_map[i] = 0;
3026 } 3026 }
3027 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { 3027 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_OS_MINORS) {
3028 snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", 3028 snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n",
3029 i, adsp_map[i]); 3029 i, adsp_map[i]);
3030 adsp_map[i] = 1; 3030 adsp_map[i] = 1;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index ece25c718e95..24271a3bd901 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 inline 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 inline 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 inline 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;
@@ -931,11 +955,11 @@ static int snd_pcm_dev_register(struct snd_device *device)
931 955
932 snd_assert(pcm != NULL && device != NULL, return -ENXIO); 956 snd_assert(pcm != NULL && device != NULL, return -ENXIO);
933 mutex_lock(&register_mutex); 957 mutex_lock(&register_mutex);
934 if (snd_pcm_search(pcm->card, pcm->device)) { 958 err = snd_pcm_add(pcm);
959 if (err) {
935 mutex_unlock(&register_mutex); 960 mutex_unlock(&register_mutex);
936 return -EBUSY; 961 return err;
937 } 962 }
938 list_add_tail(&pcm->list, &snd_pcm_devices);
939 for (cidx = 0; cidx < 2; cidx++) { 963 for (cidx = 0; cidx < 2; cidx++) {
940 int devtype = -1; 964 int devtype = -1;
941 if (pcm->streams[cidx].substream == NULL) 965 if (pcm->streams[cidx].substream == NULL)
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 1003ae375d47..838dd9ee957c 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -34,8 +34,6 @@
34#include <linux/kmod.h> 34#include <linux/kmod.h>
35#include <linux/mutex.h> 35#include <linux/mutex.h>
36 36
37#define SNDRV_OS_MINORS 256
38
39static int major = CONFIG_SND_MAJOR; 37static int major = CONFIG_SND_MAJOR;
40int snd_major; 38int snd_major;
41EXPORT_SYMBOL(snd_major); 39EXPORT_SYMBOL(snd_major);