aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@suse.cz>2005-01-03 13:33:00 +0100
committerJaroslav Kysela <perex@suse.cz>2005-01-03 13:33:00 +0100
commit59b066cadf869f3260d956a0acac2ae13231b71f (patch)
tree95e37994371cce46538fef3c5d8801b355c11008 /sound
parent63a3c990e6789e67855d2ae6765caeac27762843 (diff)
downloadhistory-59b066cadf869f3260d956a0acac2ae13231b71f.tar.gz
[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: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/control.c34
-rw-r--r--sound/core/init.c10
-rw-r--r--sound/core/sound.c22
3 files changed, 35 insertions, 31 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 2bb54ec8e9f8e3..8ec0a147dc69f7 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -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);
+}
diff --git a/sound/core/init.c b/sound/core/init.c
index 3e5eae098b629d..127f70e33b80ec 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -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 */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index e7afd376de4592..31bc97e74a41b6 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -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();