diff options
author | Jaroslav Kysela <perex@suse.cz> | 2005-01-03 13:33:00 +0100 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-01-03 13:33:00 +0100 |
commit | 59b066cadf869f3260d956a0acac2ae13231b71f (patch) | |
tree | 95e37994371cce46538fef3c5d8801b355c11008 /sound | |
parent | 63a3c990e6789e67855d2ae6765caeac27762843 (diff) | |
download | history-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.c | 34 | ||||
-rw-r--r-- | sound/core/init.c | 10 | ||||
-rw-r--r-- | sound/core/sound.c | 22 |
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(); |