diff options
Diffstat (limited to 'sound/core/sound_oss.c')
| -rw-r--r-- | sound/core/sound_oss.c | 92 |
1 files changed, 25 insertions, 67 deletions
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 726a49ac9725..d65cc6fee2e6 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -1,30 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Advanced Linux Sound Architecture * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ -#ifdef CONFIG_SND_OSSEMUL - -#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE)) -#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel." -#endif - #include <linux/init.h> #include <linux/export.h> #include <linux/slab.h> @@ -50,18 +29,16 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) if (minor >= ARRAY_SIZE(snd_oss_minors)) return NULL; - mutex_lock(&sound_oss_mutex); + guard(mutex)(&sound_oss_mutex); mreg = snd_oss_minors[minor]; if (mreg && mreg->type == type) { private_data = mreg->private_data; if (private_data && mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); + get_device(&mreg->card_ptr->card_dev); } else private_data = NULL; - mutex_unlock(&sound_oss_mutex); return private_data; } - EXPORT_SYMBOL(snd_lookup_oss_minor_data); static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) @@ -105,8 +82,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) } int snd_register_oss_device(int type, struct snd_card *card, int dev, - const struct file_operations *f_ops, void *private_data, - const char *name) + const struct file_operations *f_ops, void *private_data) { int minor = snd_oss_kernel_minor(type, card, dev); int minor_unit; @@ -129,7 +105,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->f_ops = f_ops; preg->private_data = private_data; preg->card_ptr = card; - mutex_lock(&sound_oss_mutex); + guard(mutex)(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); switch (minor_unit) { @@ -153,7 +129,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, goto __end; snd_oss_minors[track2] = preg; } - mutex_unlock(&sound_oss_mutex); return 0; __end: @@ -162,11 +137,9 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, if (register1 >= 0) unregister_sound_special(register1); snd_oss_minors[minor] = NULL; - mutex_unlock(&sound_oss_mutex); kfree(preg); return -EBUSY; } - EXPORT_SYMBOL(snd_register_oss_device); int snd_unregister_oss_device(int type, struct snd_card *card, int dev) @@ -180,13 +153,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) return 0; if (minor < 0) return minor; - mutex_lock(&sound_oss_mutex); + guard(mutex)(&sound_oss_mutex); mptr = snd_oss_minors[minor]; - if (mptr == NULL) { - mutex_unlock(&sound_oss_mutex); + if (mptr == NULL) return -ENOENT; - } - unregister_sound_special(minor); switch (SNDRV_MINOR_OSS_DEVICE(minor)) { case SNDRV_MINOR_OSS_PCM: track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO); @@ -198,26 +168,27 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); break; } - if (track2 >= 0) { - unregister_sound_special(track2); + if (track2 >= 0) snd_oss_minors[track2] = NULL; - } snd_oss_minors[minor] = NULL; - mutex_unlock(&sound_oss_mutex); + + /* call unregister_sound_special() outside sound_oss_mutex; + * otherwise may deadlock, as it can trigger the release of a card + */ + unregister_sound_special(minor); + if (track2 >= 0) + unregister_sound_special(track2); + kfree(mptr); return 0; } - EXPORT_SYMBOL(snd_unregister_oss_device); /* * INFO PART */ -#ifdef CONFIG_PROC_FS - -static struct snd_info_entry *snd_minor_info_oss_entry; - +#ifdef CONFIG_SND_PROC_FS static const char *snd_oss_device_type_name(int type) { switch (type) { @@ -243,9 +214,10 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, int minor; struct snd_minor *mptr; - mutex_lock(&sound_oss_mutex); + guard(mutex)(&sound_oss_mutex); for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) { - if (!(mptr = snd_oss_minors[minor])) + mptr = snd_oss_minors[minor]; + if (!mptr) continue; if (mptr->card >= 0) snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor, @@ -255,7 +227,6 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, snd_iprintf(buffer, "%3i: : %s\n", minor, snd_oss_device_type_name(mptr->type)); } - mutex_unlock(&sound_oss_mutex); } @@ -264,22 +235,9 @@ int __init snd_minor_info_oss_init(void) struct snd_info_entry *entry; entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); - if (entry) { - entry->c.text.read = snd_minor_info_oss_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_minor_info_oss_entry = entry; - return 0; -} - -int __exit snd_minor_info_oss_done(void) -{ - snd_info_free_entry(snd_minor_info_oss_entry); - return 0; + if (!entry) + return -ENOMEM; + entry->c.text.read = snd_minor_info_oss_read; + return snd_info_register(entry); /* freed in error path */ } -#endif /* CONFIG_PROC_FS */ - -#endif /* CONFIG_SND_OSSEMUL */ +#endif /* CONFIG_SND_PROC_FS */ |
