ALSA: vmaster - Free slave-links when freeing the master element
When freeing the vmaster master element, we should release slave-links properly, not only assumig that slaves will be freed soon later. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
aeb4b88ec0
commit
9e226b4b7e
|
@ -52,6 +52,7 @@ struct link_slave {
|
||||||
struct link_ctl_info info;
|
struct link_ctl_info info;
|
||||||
int vals[2]; /* current values */
|
int vals[2]; /* current values */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
struct snd_kcontrol *kctl; /* original kcontrol pointer */
|
||||||
struct snd_kcontrol slave; /* the copy of original control entry */
|
struct snd_kcontrol slave; /* the copy of original control entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
|
||||||
slave->count * sizeof(*slave->vd), GFP_KERNEL);
|
slave->count * sizeof(*slave->vd), GFP_KERNEL);
|
||||||
if (!srec)
|
if (!srec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
srec->kctl = slave;
|
||||||
srec->slave = *slave;
|
srec->slave = *slave;
|
||||||
memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
|
memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
|
||||||
srec->master = master_link;
|
srec->master = master_link;
|
||||||
|
@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol,
|
||||||
static void master_free(struct snd_kcontrol *kcontrol)
|
static void master_free(struct snd_kcontrol *kcontrol)
|
||||||
{
|
{
|
||||||
struct link_master *master = snd_kcontrol_chip(kcontrol);
|
struct link_master *master = snd_kcontrol_chip(kcontrol);
|
||||||
struct link_slave *slave;
|
struct link_slave *slave, *n;
|
||||||
|
|
||||||
list_for_each_entry(slave, &master->slaves, list)
|
/* free all slave links and retore the original slave kctls */
|
||||||
slave->master = NULL;
|
list_for_each_entry_safe(slave, n, &master->slaves, list) {
|
||||||
|
struct snd_kcontrol *sctl = slave->kctl;
|
||||||
|
struct list_head olist = sctl->list;
|
||||||
|
memcpy(sctl, &slave->slave, sizeof(*sctl));
|
||||||
|
memcpy(sctl->vd, slave->slave.vd,
|
||||||
|
sctl->count * sizeof(*sctl->vd));
|
||||||
|
sctl->list = olist; /* keep the current linked-list */
|
||||||
|
kfree(slave);
|
||||||
|
}
|
||||||
kfree(master);
|
kfree(master);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue