Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e226b4b authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent aeb4b88e
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct link_slave {
	struct link_ctl_info info;
	int vals[2];		/* current values */
	unsigned int flags;
	struct snd_kcontrol *kctl; /* original kcontrol pointer */
	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);
	if (!srec)
		return -ENOMEM;
	srec->kctl = slave;
	srec->slave = *slave;
	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
	srec->master = master_link;
@@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol,
static void master_free(struct snd_kcontrol *kcontrol)
{
	struct link_master *master = snd_kcontrol_chip(kcontrol);
	struct link_slave *slave;

	list_for_each_entry(slave, &master->slaves, list)
		slave->master = NULL;
	struct link_slave *slave, *n;

	/* free all slave links and retore the original slave kctls */
	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);
}