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 ...@@ -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_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); 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_create(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_register_ioctl(snd_kctl_ioctl_func_t fcn); int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_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; ...@@ -49,6 +49,7 @@ struct sbus_dev;
typedef enum { typedef enum {
SNDRV_DEV_TOPLEVEL = (0*SNDRV_DEV_TYPE_RANGE_SIZE), SNDRV_DEV_TOPLEVEL = (0*SNDRV_DEV_TYPE_RANGE_SIZE),
SNDRV_DEV_CONTROL,
SNDRV_DEV_LOWLEVEL_PRE, SNDRV_DEV_LOWLEVEL_PRE,
SNDRV_DEV_LOWLEVEL_NORMAL = (1*SNDRV_DEV_TYPE_RANGE_SIZE), SNDRV_DEV_LOWLEVEL_NORMAL = (1*SNDRV_DEV_TYPE_RANGE_SIZE),
SNDRV_DEV_PCM, SNDRV_DEV_PCM,
......
...@@ -1274,11 +1274,11 @@ static snd_minor_t snd_ctl_reg = ...@@ -1274,11 +1274,11 @@ static snd_minor_t snd_ctl_reg =
}; };
/* /*
* registration of the control device: * registration of the control device
* called from init.c
*/ */
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; int err, cardnum;
char name[16]; char name[16];
...@@ -1293,11 +1293,11 @@ int snd_ctl_register(snd_card_t *card) ...@@ -1293,11 +1293,11 @@ int snd_ctl_register(snd_card_t *card)
} }
/* /*
* disconnection of the control device: * disconnection of the control device
* called from init.c
*/ */
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; struct list_head *flist;
snd_ctl_file_t *ctl; snd_ctl_file_t *ctl;
...@@ -1312,11 +1312,11 @@ int snd_ctl_disconnect(snd_card_t *card) ...@@ -1312,11 +1312,11 @@ int snd_ctl_disconnect(snd_card_t *card)
} }
/* /*
* de-registration of the control device: * de-registration of the control device
* called from init.c
*/ */
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; int err, cardnum;
snd_kcontrol_t *control; snd_kcontrol_t *control;
...@@ -1333,3 +1333,19 @@ int snd_ctl_unregister(snd_card_t *card) ...@@ -1333,3 +1333,19 @@ int snd_ctl_unregister(snd_card_t *card)
up_write(&card->controls_rwsem); up_write(&card->controls_rwsem);
return 0; 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, ...@@ -124,7 +124,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
#endif #endif
/* the control interface cannot be accessed from the user space until */ /* the control interface cannot be accessed from the user space until */
/* snd_cards_bitmask and snd_cards are set with snd_card_register */ /* 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"); snd_printd("unable to register control minors\n");
goto __error; goto __error;
} }
...@@ -137,7 +137,7 @@ snd_card_t *snd_card_new(int idx, const char *xid, ...@@ -137,7 +137,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
return card; return card;
__error_ctl: __error_ctl:
snd_ctl_unregister(card); snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error: __error:
kfree(card); kfree(card);
return NULL; return NULL;
...@@ -216,8 +216,6 @@ int snd_card_disconnect(snd_card_t * card) ...@@ -216,8 +216,6 @@ int snd_card_disconnect(snd_card_t * card)
/* phase 3: notify all connected devices about disconnection */ /* phase 3: notify all connected devices about disconnection */
/* at this point, they cannot respond to any calls except release() */ /* 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 defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback) if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
...@@ -277,10 +275,6 @@ int snd_card_free(snd_card_t * card) ...@@ -277,10 +275,6 @@ int snd_card_free(snd_card_t * card)
snd_printk(KERN_ERR "unable to free all devices (normal)\n"); snd_printk(KERN_ERR "unable to free all devices (normal)\n");
/* Fatal, but this situation should never occur */ /* 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) { if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
snd_printk(KERN_ERR "unable to free all devices (post)\n"); snd_printk(KERN_ERR "unable to free all devices (post)\n");
/* Fatal, but this situation should never occur */ /* 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, ...@@ -228,12 +228,11 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg,
return -EBUSY; return -EBUSY;
} }
list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]); 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); devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
if (card) if (card)
device = card->dev; device = card->dev;
class_simple_device_add(sound_class, MKDEV(major, minor), device, name); class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
}
up(&sound_mutex); up(&sound_mutex);
return 0; return 0;
...@@ -263,10 +262,9 @@ int snd_unregister_device(int type, snd_card_t * card, int dev) ...@@ -263,10 +262,9 @@ int snd_unregister_device(int type, snd_card_t * card, int dev)
return -EINVAL; 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); devfs_remove("snd/%s", mptr->name);
class_simple_device_remove(MKDEV(major, minor)); class_simple_device_remove(MKDEV(major, minor));
}
list_del(&mptr->list); list_del(&mptr->list);
up(&sound_mutex); up(&sound_mutex);
...@@ -357,10 +355,8 @@ static int __init alsa_sound_init(void) ...@@ -357,10 +355,8 @@ static int __init alsa_sound_init(void)
return -ENOMEM; return -ENOMEM;
} }
snd_info_minor_register(); 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); 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 #ifndef MODULE
printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
#endif #endif
...@@ -371,10 +367,8 @@ static void __exit alsa_sound_exit(void) ...@@ -371,10 +367,8 @@ static void __exit alsa_sound_exit(void)
{ {
short controlnum; short controlnum;
for (controlnum = 0; controlnum < cards_limit; controlnum++) { for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_remove("snd/controlC%d", controlnum); devfs_remove("snd/controlC%d", controlnum);
class_simple_device_remove(MKDEV(major, controlnum<<5));
}
snd_info_minor_unregister(); snd_info_minor_unregister();
snd_info_done(); 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