Commit 59b066ca authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Fix creation of control devices over udev

Control Midlevel,ALSA Core
Don't create control devices before the driver initialization finishes
(ALSA BTS #742).

The control device is now handled in the device list together with others
(holding the card instance as the device pointer).
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 63a3c990
......@@ -115,10 +115,8 @@ int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem
snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid);
snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id);
int snd_ctl_register(snd_card_t *card);
int snd_ctl_disconnect(snd_card_t *card);
int snd_ctl_can_unregister(snd_card_t *card);
int snd_ctl_unregister(snd_card_t *card);
int snd_ctl_create(snd_card_t *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
......
......@@ -49,6 +49,7 @@ struct sbus_dev;
typedef enum {
SNDRV_DEV_TOPLEVEL = (0*SNDRV_DEV_TYPE_RANGE_SIZE),
SNDRV_DEV_CONTROL,
SNDRV_DEV_LOWLEVEL_PRE,
SNDRV_DEV_LOWLEVEL_NORMAL = (1*SNDRV_DEV_TYPE_RANGE_SIZE),
SNDRV_DEV_PCM,
......
......@@ -1274,11 +1274,11 @@ static snd_minor_t snd_ctl_reg =
};
/*
* registration of the control device:
* called from init.c
* registration of the control device
*/
int snd_ctl_register(snd_card_t *card)
static int snd_ctl_dev_register(snd_device_t *device)
{
snd_card_t *card = device->device_data;
int err, cardnum;
char name[16];
......@@ -1293,11 +1293,11 @@ int snd_ctl_register(snd_card_t *card)
}
/*
* disconnection of the control device:
* called from init.c
* disconnection of the control device
*/
int snd_ctl_disconnect(snd_card_t *card)
static int snd_ctl_dev_disconnect(snd_device_t *device)
{
snd_card_t *card = device->device_data;
struct list_head *flist;
snd_ctl_file_t *ctl;
......@@ -1312,11 +1312,11 @@ int snd_ctl_disconnect(snd_card_t *card)
}
/*
* de-registration of the control device:
* called from init.c
* de-registration of the control device
*/
int snd_ctl_unregister(snd_card_t *card)
static int snd_ctl_dev_unregister(snd_device_t *device)
{
snd_card_t *card = device->device_data;
int err, cardnum;
snd_kcontrol_t *control;
......@@ -1333,3 +1333,19 @@ int snd_ctl_unregister(snd_card_t *card)
up_write(&card->controls_rwsem);
return 0;
}
/*
* create control core:
* called from init.c
*/
int snd_ctl_create(snd_card_t *card)
{
static snd_device_ops_t ops = {
.dev_register = snd_ctl_dev_register,
.dev_disconnect = snd_ctl_dev_disconnect,
.dev_unregister = snd_ctl_dev_unregister
};
snd_assert(card != NULL, return -ENXIO);
return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
}
......@@ -124,7 +124,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
#endif
/* the control interface cannot be accessed from the user space until */
/* snd_cards_bitmask and snd_cards are set with snd_card_register */
if ((err = snd_ctl_register(card)) < 0) {
if ((err = snd_ctl_create(card)) < 0) {
snd_printd("unable to register control minors\n");
goto __error;
}
......@@ -137,7 +137,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
return card;
__error_ctl:
snd_ctl_unregister(card);
snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error:
kfree(card);
return NULL;
......@@ -216,8 +216,6 @@ int snd_card_disconnect(snd_card_t * card)
/* phase 3: notify all connected devices about disconnection */
/* at this point, they cannot respond to any calls except release() */
snd_ctl_disconnect(card);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
......@@ -277,10 +275,6 @@ int snd_card_free(snd_card_t * card)
snd_printk(KERN_ERR "unable to free all devices (normal)\n");
/* Fatal, but this situation should never occur */
}
if (snd_ctl_unregister(card) < 0) {
snd_printk(KERN_ERR "unable to unregister control minors\n");
/* Not fatal error */
}
if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
snd_printk(KERN_ERR "unable to free all devices (post)\n");
/* Fatal, but this situation should never occur */
......
......@@ -228,12 +228,11 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg,
return -EBUSY;
}
list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]);
if (strncmp(name, "controlC", 8) || card->number >= cards_limit) {
if (strncmp(name, "controlC", 8) || card->number >= cards_limit)
devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
if (card)
device = card->dev;
class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
}
if (card)
device = card->dev;
class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
up(&sound_mutex);
return 0;
......@@ -263,10 +262,9 @@ int snd_unregister_device(int type, snd_card_t * card, int dev)
return -EINVAL;
}
if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) { /* created in sound.c */
if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */
devfs_remove("snd/%s", mptr->name);
class_simple_device_remove(MKDEV(major, minor));
}
class_simple_device_remove(MKDEV(major, minor));
list_del(&mptr->list);
up(&sound_mutex);
......@@ -357,10 +355,8 @@ static int __init alsa_sound_init(void)
return -ENOMEM;
}
snd_info_minor_register();
for (controlnum = 0; controlnum < cards_limit; controlnum++) {
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
class_simple_device_add(sound_class, MKDEV(major, controlnum<<5), NULL, "controlC%d", controlnum);
}
#ifndef MODULE
printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
#endif
......@@ -371,10 +367,8 @@ static void __exit alsa_sound_exit(void)
{
short controlnum;
for (controlnum = 0; controlnum < cards_limit; controlnum++) {
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_remove("snd/controlC%d", controlnum);
class_simple_device_remove(MKDEV(major, controlnum<<5));
}
snd_info_minor_unregister();
snd_info_done();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment