diff options
author | Pawel MOLL <pawel.moll@st.com> | 2008-07-29 12:34:26 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-07-29 15:32:48 -0400 |
commit | 9423969005586e6e27ca380e01b4a8c50698e2af (patch) | |
tree | 818bef3892109c05a4ad5ec3ae5e90dd4436c0c6 /sound | |
parent | 815ecf8dec95d07e260a16ebe8409f4b7c0fdc0f (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.c | 10 | ||||
-rw-r--r-- | sound/core/pcm.c | 50 | ||||
-rw-r--r-- | sound/core/sound.c | 2 |
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) | |||
2947 | static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) | 2947 | static 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); | |||
42 | static int snd_pcm_dev_register(struct snd_device *device); | 42 | static int snd_pcm_dev_register(struct snd_device *device); |
43 | static int snd_pcm_dev_disconnect(struct snd_device *device); | 43 | static int snd_pcm_dev_disconnect(struct snd_device *device); |
44 | 44 | ||
45 | static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) | 45 | static 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 | ||
56 | static 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 | |||
69 | static 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 | |||
56 | static int snd_pcm_control_ioctl(struct snd_card *card, | 87 | static 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(®ister_mutex); | 98 | mutex_lock(®ister_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(®ister_mutex); | 100 | mutex_unlock(®ister_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(®ister_mutex); | 124 | mutex_lock(®ister_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(®ister_mutex); | 957 | mutex_lock(®ister_mutex); |
934 | if (snd_pcm_search(pcm->card, pcm->device)) { | 958 | err = snd_pcm_add(pcm); |
959 | if (err) { | ||
935 | mutex_unlock(®ister_mutex); | 960 | mutex_unlock(®ister_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 | |||
39 | static int major = CONFIG_SND_MAJOR; | 37 | static int major = CONFIG_SND_MAJOR; |
40 | int snd_major; | 38 | int snd_major; |
41 | EXPORT_SYMBOL(snd_major); | 39 | EXPORT_SYMBOL(snd_major); |