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:
@@ -120,19 +120,12 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(snd_lookup_minor_data);
|
EXPORT_SYMBOL(snd_lookup_minor_data);
|
||||||
|
|
||||||
static int __snd_open(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
unsigned int minor = iminor(inode);
|
|
||||||
struct snd_minor *mptr = NULL;
|
|
||||||
const struct file_operations *old_fops;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (minor >= ARRAY_SIZE(snd_minors))
|
|
||||||
return -ENODEV;
|
|
||||||
mptr = snd_minors[minor];
|
|
||||||
if (mptr == NULL) {
|
|
||||||
#ifdef CONFIG_MODULES
|
#ifdef CONFIG_MODULES
|
||||||
int dev = SNDRV_MINOR_DEVICE(minor);
|
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) {
|
if (dev == SNDRV_MINOR_CONTROL) {
|
||||||
/* /dev/aloadC? */
|
/* /dev/aloadC? */
|
||||||
int card = SNDRV_MINOR_CARD(minor);
|
int card = SNDRV_MINOR_CARD(minor);
|
||||||
@@ -142,42 +135,52 @@ static int __snd_open(struct inode *inode, struct file *file)
|
|||||||
/* /dev/aloadSEQ */
|
/* /dev/aloadSEQ */
|
||||||
snd_request_other(minor);
|
snd_request_other(minor);
|
||||||
}
|
}
|
||||||
#ifndef CONFIG_SND_DYNAMIC_MINORS
|
mutex_lock(&sound_mutex); /* reacuire lock */
|
||||||
/* /dev/snd/{controlC?,seq} */
|
return snd_minors[minor];
|
||||||
mptr = snd_minors[minor];
|
}
|
||||||
if (mptr == NULL)
|
#else /* !CONFIG_MODULES */
|
||||||
#endif
|
#define autoload_device(minor) NULL
|
||||||
#endif
|
#endif /* CONFIG_MODULES */
|
||||||
|
|
||||||
|
static int snd_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
unsigned int minor = iminor(inode);
|
||||||
|
struct snd_minor *mptr = NULL;
|
||||||
|
const struct file_operations *old_fops;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (minor >= ARRAY_SIZE(snd_minors))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
mutex_lock(&sound_mutex);
|
||||||
|
mptr = snd_minors[minor];
|
||||||
|
if (mptr == NULL) {
|
||||||
|
mptr = autoload_device(minor);
|
||||||
|
if (!mptr) {
|
||||||
|
mutex_unlock(&sound_mutex);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
old_fops = file->f_op;
|
old_fops = file->f_op;
|
||||||
file->f_op = fops_get(mptr->f_ops);
|
file->f_op = fops_get(mptr->f_ops);
|
||||||
if (file->f_op == NULL) {
|
if (file->f_op == NULL) {
|
||||||
file->f_op = old_fops;
|
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);
|
err = file->f_op->open(inode, file);
|
||||||
if (err) {
|
if (err) {
|
||||||
fops_put(file->f_op);
|
fops_put(file->f_op);
|
||||||
file->f_op = fops_get(old_fops);
|
file->f_op = fops_get(old_fops);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fops_put(old_fops);
|
fops_put(old_fops);
|
||||||
return err;
|
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 =
|
static const struct file_operations snd_fops =
|
||||||
{
|
{
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
Reference in New Issue
Block a user