Unverified Commit ae4bafea authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9998 ALSA: hda/cs_dsp_ctl: Use private_free for control cleanup

parents 2c096246 774cb298
Loading
Loading
Loading
Loading
+31 −16
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include <linux/module.h>
#include <sound/soc.h>
#include <linux/cleanup.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
#include "hda_cs_dsp_ctl.h"
@@ -97,11 +98,23 @@ static unsigned int wmfw_convert_flags(unsigned int in)
	return out;
}

static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name)
static void hda_cs_dsp_free_kcontrol(struct snd_kcontrol *kctl)
{
	struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;

	/* NULL priv to prevent a double-free in hda_cs_dsp_control_remove() */
	cs_ctl->priv = NULL;
	kfree(ctl);
}

static void hda_cs_dsp_add_kcontrol(struct cs_dsp_coeff_ctl *cs_ctl,
				    const struct hda_cs_dsp_ctl_info *info,
				    const char *name)
{
	struct snd_kcontrol_new kcontrol = {0};
	struct snd_kcontrol *kctl;
	struct hda_cs_dsp_coeff_ctl *ctl __free(kfree) = NULL;
	int ret = 0;

	if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) {
@@ -110,6 +123,13 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char
		return;
	}

	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
	if (!ctl)
		return;

	ctl->cs_ctl = cs_ctl;
	ctl->card = info->card;

	kcontrol.name = name;
	kcontrol.info = hda_cs_dsp_coeff_info;
	kcontrol.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -117,20 +137,22 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char
	kcontrol.get = hda_cs_dsp_coeff_get;
	kcontrol.put = hda_cs_dsp_coeff_put;

	/* Save ctl inside private_data, ctl is owned by cs_dsp,
	 * and will be freed when cs_dsp removes the control */
	kctl = snd_ctl_new1(&kcontrol, (void *)ctl);
	if (!kctl)
		return;

	ret = snd_ctl_add(ctl->card, kctl);
	kctl->private_free = hda_cs_dsp_free_kcontrol;
	ctl->kctl = kctl;

	/* snd_ctl_add() calls our private_free on error, which will kfree(ctl) */
	cs_ctl->priv = no_free_ptr(ctl);
	ret = snd_ctl_add(info->card, kctl);
	if (ret) {
		dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret);
		return;
	}

	dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name);
	ctl->kctl = kctl;
}

static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
@@ -138,7 +160,6 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
{
	struct cs_dsp *cs_dsp = cs_ctl->dsp;
	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
	struct hda_cs_dsp_coeff_ctl *ctl;
	const char *region_name;
	int ret;

@@ -163,15 +184,7 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
			 " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
	}

	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
	if (!ctl)
		return;

	ctl->cs_ctl = cs_ctl;
	ctl->card = info->card;
	cs_ctl->priv = ctl;

	hda_cs_dsp_add_kcontrol(ctl, name);
	hda_cs_dsp_add_kcontrol(cs_ctl, info, name);
}

void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info)
@@ -203,7 +216,9 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
{
	struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv;

	kfree(ctl);
	/* ctl and kctl may already have been removed by ALSA private_free */
	if (ctl && ctl->kctl)
		snd_ctl_remove(ctl->card, ctl->kctl);
}
EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS);