mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
ALSA: Remove BKL from open multiplexer
Use a local mutex instead of BKL. This should suffice since each device type has also its open_mutex. Also, a bit of clean-up of the legacy device auto-loading code. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
5b5cd553e3
commit
4cf19b848f
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user