From 9423969005586e6e27ca380e01b4a8c50698e2af Mon Sep 17 00:00:00 2001 From: Pawel MOLL Date: Tue, 29 Jul 2008 17:34:26 +0100 Subject: 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 Signed-off-by: Jaroslav Kysela --- sound/core/pcm.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'sound/core/pcm.c') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ece25c7..24271a3 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); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) +static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) return NULL; } +static inline int snd_pcm_next(struct snd_card *card, int device) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == card && pcm->device > device) + return pcm->device; + else if (pcm->card->number > card->number) + return -1; + } + return -1; +} + +static inline int snd_pcm_add(struct snd_pcm *newpcm) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == newpcm->card && pcm->device == newpcm->device) + return -EBUSY; + if (pcm->card->number > newpcm->card->number || + (pcm->card == newpcm->card && + pcm->device > newpcm->device)) { + list_add(&newpcm->list, pcm->list.prev); + return 0; + } + } + list_add_tail(&newpcm->list, &snd_pcm_devices); + return 0; +} + static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; - while (device < SNDRV_PCM_DEVICES) { - if (snd_pcm_search(card, device)) - break; - device++; - } - if (device == SNDRV_PCM_DEVICES) - device = -1; + device = snd_pcm_next(card, device); mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_search(card, device); + pcm = snd_pcm_get(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -931,11 +955,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - if (snd_pcm_search(pcm->card, pcm->device)) { + err = snd_pcm_add(pcm); + if (err) { mutex_unlock(®ister_mutex); - return -EBUSY; + return err; } - list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) -- cgit v1.1 From 896e6cc20e67038af12e1a7711eef32647e62f23 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 1 Aug 2008 13:36:04 +0200 Subject: sound: Revert "ALSA: Fix limit of 8 PCM devices in SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE" This reverts commit fb3d6f2b77bdec75d45aa9d4464287ed87927866. New, updated patch with same subject replaces this commit. Signed-off-by: Jaroslav Kysela --- sound/core/pcm.c | 50 +++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) (limited to 'sound/core/pcm.c') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 24271a3..ece25c7 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); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) +static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,37 +53,6 @@ static inline struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) return NULL; } -static inline int snd_pcm_next(struct snd_card *card, int device) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == card && pcm->device > device) - return pcm->device; - else if (pcm->card->number > card->number) - return -1; - } - return -1; -} - -static inline int snd_pcm_add(struct snd_pcm *newpcm) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == newpcm->card && pcm->device == newpcm->device) - return -EBUSY; - if (pcm->card->number > newpcm->card->number || - (pcm->card == newpcm->card && - pcm->device > newpcm->device)) { - list_add(&newpcm->list, pcm->list.prev); - return 0; - } - } - list_add_tail(&newpcm->list, &snd_pcm_devices); - return 0; -} - static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -96,7 +65,14 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = snd_pcm_next(card, device); + device = device < 0 ? 0 : device + 1; + while (device < SNDRV_PCM_DEVICES) { + if (snd_pcm_search(card, device)) + break; + device++; + } + if (device == SNDRV_PCM_DEVICES) + device = -1; mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -122,7 +98,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_get(card, device); + pcm = snd_pcm_search(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -955,11 +931,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - err = snd_pcm_add(pcm); - if (err) { + if (snd_pcm_search(pcm->card, pcm->device)) { mutex_unlock(®ister_mutex); - return err; + return -EBUSY; } + list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) -- cgit v1.1 From f90c06a2b613eea24a77d56f24b084745c43713d Mon Sep 17 00:00:00 2001 From: Pawel MOLL Date: Wed, 30 Jul 2008 12:46:40 +0100 Subject: 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. Additionally the device field of struct snd_pcm had to be changed to int, as its "unsignednity" caused a lot of problems when comparing it to potentially negative signed values. (-1 is 0xffffffff or even more then ;-) Signed-off-by: Pawel Moll Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/pcm.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'sound/core/pcm.c') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index ece25c7..517388b 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); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); -static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) +static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) { struct snd_pcm *pcm; @@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) return NULL; } +static int snd_pcm_next(struct snd_card *card, int device) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == card && pcm->device > device) + return pcm->device; + else if (pcm->card->number > card->number) + return -1; + } + return -1; +} + +static int snd_pcm_add(struct snd_pcm *newpcm) +{ + struct snd_pcm *pcm; + + list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->card == newpcm->card && pcm->device == newpcm->device) + return -EBUSY; + if (pcm->card->number > newpcm->card->number || + (pcm->card == newpcm->card && + pcm->device > newpcm->device)) { + list_add(&newpcm->list, pcm->list.prev); + return 0; + } + } + list_add_tail(&newpcm->list, &snd_pcm_devices); + return 0; +} + static int snd_pcm_control_ioctl(struct snd_card *card, struct snd_ctl_file *control, unsigned int cmd, unsigned long arg) @@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; - while (device < SNDRV_PCM_DEVICES) { - if (snd_pcm_search(card, device)) - break; - device++; - } - if (device == SNDRV_PCM_DEVICES) - device = -1; + device = snd_pcm_next(card, device); mutex_unlock(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; @@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(subdevice, &info->subdevice)) return -EFAULT; mutex_lock(®ister_mutex); - pcm = snd_pcm_search(card, device); + pcm = snd_pcm_get(card, device); if (pcm == NULL) { err = -ENXIO; goto _error; @@ -931,11 +955,11 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_assert(pcm != NULL && device != NULL, return -ENXIO); mutex_lock(®ister_mutex); - if (snd_pcm_search(pcm->card, pcm->device)) { + err = snd_pcm_add(pcm); + if (err) { mutex_unlock(®ister_mutex); - return -EBUSY; + return err; } - list_add_tail(&pcm->list, &snd_pcm_devices); for (cidx = 0; cidx < 2; cidx++) { int devtype = -1; if (pcm->streams[cidx].substream == NULL) -- cgit v1.1 From 7eaa943c8ed8e91e05d0f5d0dc7a18e3319b45cf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 8 Aug 2008 17:09:09 +0200 Subject: ALSA: Kill snd_assert() in sound/core/* Kill snd_assert() in sound/core/*, either removed or replaced with if () with snd_BUG_ON(). Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/core/pcm.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'sound/core/pcm.c') diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 517388b..192a433 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -256,7 +256,6 @@ static char *snd_pcm_tstamp_mode_names[] = { static const char *snd_pcm_stream_name(int stream) { - snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL); return snd_pcm_stream_names[stream]; } @@ -272,7 +271,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) static const char *snd_pcm_tstamp_mode_name(int mode) { - snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL); return snd_pcm_tstamp_mode_names[mode]; } @@ -706,9 +704,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, .dev_disconnect = snd_pcm_dev_disconnect, }; - snd_assert(rpcm != NULL, return -EINVAL); - *rpcm = NULL; - snd_assert(card != NULL, return -ENXIO); + if (snd_BUG_ON(!card)) + return -ENXIO; + if (rpcm) + *rpcm = NULL; pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) { snd_printk(KERN_ERR "Cannot allocate PCM\n"); @@ -732,7 +731,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, snd_pcm_free(pcm); return err; } - *rpcm = pcm; + if (rpcm) + *rpcm = pcm; return 0; } @@ -766,7 +766,8 @@ static int snd_pcm_free(struct snd_pcm *pcm) { struct snd_pcm_notify *notify; - snd_assert(pcm != NULL, return -ENXIO); + if (!pcm) + return 0; list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_unregister(pcm); } @@ -797,9 +798,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, int prefer_subdevice = -1; size_t size; - snd_assert(rsubstream != NULL, return -EINVAL); + if (snd_BUG_ON(!pcm || !rsubstream)) + return -ENXIO; *rsubstream = NULL; - snd_assert(pcm != NULL, return -ENXIO); pstr = &pcm->streams[stream]; if (pstr->substream == NULL || pstr->substream_count == 0) return -ENODEV; @@ -907,8 +908,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; + if (PCM_RUNTIME_CHECK(substream)) + return; runtime = substream->runtime; - snd_assert(runtime != NULL, return); if (runtime->private_free != NULL) runtime->private_free(runtime); snd_free_pages((void*)runtime->status, @@ -953,7 +955,8 @@ static int snd_pcm_dev_register(struct snd_device *device) struct snd_pcm *pcm = device->device_data; struct device *dev; - snd_assert(pcm != NULL && device != NULL, return -ENXIO); + if (snd_BUG_ON(!pcm || !device)) + return -ENXIO; mutex_lock(®ister_mutex); err = snd_pcm_add(pcm); if (err) { @@ -1043,10 +1046,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) { struct snd_pcm *pcm; - snd_assert(notify != NULL && - notify->n_register != NULL && - notify->n_unregister != NULL && - notify->n_disconnect, return -EINVAL); + if (snd_BUG_ON(!notify || + !notify->n_register || + !notify->n_unregister || + !notify->n_disconnect)) + return -EINVAL; mutex_lock(®ister_mutex); if (nfree) { list_del(¬ify->list); -- cgit v1.1