|
@@ -120,7 +120,29 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
|
|
|
|
|
|
EXPORT_SYMBOL(snd_lookup_minor_data);
|
|
|
|
|
|
-static int __snd_open(struct inode *inode, struct file *file)
|
|
|
+#ifdef CONFIG_MODULES
|
|
|
+static struct snd_minor *autoload_device(unsigned int minor)
|
|
|
+{
|
|
|
+ int dev;
|
|
|
+ mutex_unlock(&sound_mutex); /* release lock temporarily */
|
|
|
+ dev = SNDRV_MINOR_DEVICE(minor);
|
|
|
+ if (dev == SNDRV_MINOR_CONTROL) {
|
|
|
+ /* /dev/aloadC? */
|
|
|
+ int card = SNDRV_MINOR_CARD(minor);
|
|
|
+ if (snd_cards[card] == NULL)
|
|
|
+ snd_request_card(card);
|
|
|
+ } else if (dev == SNDRV_MINOR_GLOBAL) {
|
|
|
+ /* /dev/aloadSEQ */
|
|
|
+ snd_request_other(minor);
|
|
|
+ }
|
|
|
+ mutex_lock(&sound_mutex); /* reacuire lock */
|
|
|
+ return snd_minors[minor];
|
|
|
+}
|
|
|
+#else /* !CONFIG_MODULES */
|
|
|
+#define autoload_device(minor) NULL
|
|
|
+#endif /* CONFIG_MODULES */
|
|
|
+
|
|
|
+static int snd_open(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
unsigned int minor = iminor(inode);
|
|
|
struct snd_minor *mptr = NULL;
|
|
@@ -129,55 +151,36 @@ static int __snd_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
if (minor >= ARRAY_SIZE(snd_minors))
|
|
|
return -ENODEV;
|
|
|
+ mutex_lock(&sound_mutex);
|
|
|
mptr = snd_minors[minor];
|
|
|
if (mptr == NULL) {
|
|
|
-#ifdef CONFIG_MODULES
|
|
|
- int dev = SNDRV_MINOR_DEVICE(minor);
|
|
|
- if (dev == SNDRV_MINOR_CONTROL) {
|
|
|
- /* /dev/aloadC? */
|
|
|
- int card = SNDRV_MINOR_CARD(minor);
|
|
|
- if (snd_cards[card] == NULL)
|
|
|
- snd_request_card(card);
|
|
|
- } else if (dev == SNDRV_MINOR_GLOBAL) {
|
|
|
- /* /dev/aloadSEQ */
|
|
|
- snd_request_other(minor);
|
|
|
- }
|
|
|
-#ifndef CONFIG_SND_DYNAMIC_MINORS
|
|
|
- /* /dev/snd/{controlC?,seq} */
|
|
|
- mptr = snd_minors[minor];
|
|
|
- if (mptr == NULL)
|
|
|
-#endif
|
|
|
-#endif
|
|
|
+ mptr = autoload_device(minor);
|
|
|
+ if (!mptr) {
|
|
|
+ mutex_unlock(&sound_mutex);
|
|
|
return -ENODEV;
|
|
|
+ }
|
|
|
}
|
|
|
old_fops = file->f_op;
|
|
|
file->f_op = fops_get(mptr->f_ops);
|
|
|
if (file->f_op == NULL) {
|
|
|
file->f_op = old_fops;
|
|
|
- return -ENODEV;
|
|
|
+ err = -ENODEV;
|
|
|
}
|
|
|
- if (file->f_op->open)
|
|
|
+ mutex_unlock(&sound_mutex);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (file->f_op->open) {
|
|
|
err = file->f_op->open(inode, file);
|
|
|
- if (err) {
|
|
|
- fops_put(file->f_op);
|
|
|
- file->f_op = fops_get(old_fops);
|
|
|
+ if (err) {
|
|
|
+ fops_put(file->f_op);
|
|
|
+ file->f_op = fops_get(old_fops);
|
|
|
+ }
|
|
|
}
|
|
|
fops_put(old_fops);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/* BKL pushdown: nasty #ifdef avoidance wrapper */
|
|
|
-static int snd_open(struct inode *inode, struct file *file)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- lock_kernel();
|
|
|
- ret = __snd_open(inode, file);
|
|
|
- unlock_kernel();
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
static const struct file_operations snd_fops =
|
|
|
{
|
|
|
.owner = THIS_MODULE,
|