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

Commit 3103c08f authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: control: Consolidate helpers for adding and replacing ctl elements



Both snd_ctl_add() and snd_ctl_replace() process the things in a
fairly similar way, and indeed the most of the codes can be unified.

This patch is a refactoring to consolidate the both functions to call
a single helper with an extra "mode" argument.  There should be no
functional difference, except for one additional sanity check applied
now to snd_ctl_replace() (which was rather overlooking, IMO), too.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5f2ad594
Loading
Loading
Loading
Loading
+52 −71
Original line number Diff line number Diff line
@@ -348,24 +348,43 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
	return 0;
}

/* add a new kcontrol object; call with card->controls_rwsem locked */
static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
enum snd_ctl_add_mode {
	CTL_ADD_EXCLUSIVE, CTL_REPLACE, CTL_ADD_ON_REPLACE,
};

/* add/replace a new kcontrol object; call with card->controls_rwsem locked */
static int __snd_ctl_add_replace(struct snd_card *card,
				 struct snd_kcontrol *kcontrol,
				 enum snd_ctl_add_mode mode)
{
	struct snd_ctl_elem_id id;
	unsigned int idx;
	unsigned int count;
	struct snd_kcontrol *old;
	int err;

	id = kcontrol->id;
	if (id.index > UINT_MAX - kcontrol->count)
		return -EINVAL;

	if (snd_ctl_find_id(card, &id)) {
	old = snd_ctl_find_id(card, &id);
	if (!old) {
		if (mode == CTL_REPLACE)
			return -EINVAL;
	} else {
		if (mode == CTL_ADD_EXCLUSIVE) {
			dev_err(card->dev,
				"control %i:%i:%i:%s:%i is already present\n",
			id.iface, id.device, id.subdevice, id.name, id.index);
				id.iface, id.device, id.subdevice, id.name,
				id.index);
			return -EBUSY;
		}

		err = snd_ctl_remove(card, old);
		if (err < 0)
			return err;
	}

	if (snd_ctl_find_hole(card, kcontrol->count) < 0)
		return -ENOMEM;

@@ -382,21 +401,9 @@ static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
	return 0;
}

/**
 * snd_ctl_add - add the control instance to the card
 * @card: the card instance
 * @kcontrol: the control instance to add
 *
 * Adds the control instance created via snd_ctl_new() or
 * snd_ctl_new1() to the given card. Assigns also an unique
 * numid used for fast search.
 *
 * It frees automatically the control which cannot be added.
 *
 * Return: Zero if successful, or a negative error code on failure.
 *
 */
int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
static int snd_ctl_add_replace(struct snd_card *card,
			       struct snd_kcontrol *kcontrol,
			       enum snd_ctl_add_mode mode)
{
	int err = -EINVAL;

@@ -406,7 +413,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
		goto error;

	down_write(&card->controls_rwsem);
	err = __snd_ctl_add(card, kcontrol);
	err = __snd_ctl_add_replace(card, kcontrol, mode);
	up_write(&card->controls_rwsem);
	if (err < 0)
		goto error;
@@ -416,6 +423,25 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
	snd_ctl_free_one(kcontrol);
	return err;
}

/**
 * snd_ctl_add - add the control instance to the card
 * @card: the card instance
 * @kcontrol: the control instance to add
 *
 * Adds the control instance created via snd_ctl_new() or
 * snd_ctl_new1() to the given card. Assigns also an unique
 * numid used for fast search.
 *
 * It frees automatically the control which cannot be added.
 *
 * Return: Zero if successful, or a negative error code on failure.
 *
 */
int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
	return snd_ctl_add_replace(card, kcontrol, CTL_ADD_EXCLUSIVE);
}
EXPORT_SYMBOL(snd_ctl_add);

/**
@@ -435,53 +461,8 @@ EXPORT_SYMBOL(snd_ctl_add);
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
		    bool add_on_replace)
{
	struct snd_ctl_elem_id id;
	unsigned int count;
	unsigned int idx;
	struct snd_kcontrol *old;
	int ret;

	if (!kcontrol)
		return -EINVAL;
	if (snd_BUG_ON(!card || !kcontrol->info)) {
		ret = -EINVAL;
		goto error;
	}
	id = kcontrol->id;
	down_write(&card->controls_rwsem);
	old = snd_ctl_find_id(card, &id);
	if (!old) {
		if (add_on_replace)
			goto add;
		up_write(&card->controls_rwsem);
		ret = -EINVAL;
		goto error;
	}
	ret = snd_ctl_remove(card, old);
	if (ret < 0) {
		up_write(&card->controls_rwsem);
		goto error;
	}
add:
	if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
		up_write(&card->controls_rwsem);
		ret = -ENOMEM;
		goto error;
	}
	list_add_tail(&kcontrol->list, &card->controls);
	card->controls_count += kcontrol->count;
	kcontrol->id.numid = card->last_numid + 1;
	card->last_numid += kcontrol->count;
	id = kcontrol->id;
	count = kcontrol->count;
	up_write(&card->controls_rwsem);
	for (idx = 0; idx < count; idx++, id.index++, id.numid++)
		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
	return 0;

error:
	snd_ctl_free_one(kcontrol);
	return ret;
	return snd_ctl_add_replace(card, kcontrol,
				   add_on_replace ? CTL_ADD_ON_REPLACE : CTL_REPLACE);
}
EXPORT_SYMBOL(snd_ctl_replace);

@@ -1369,7 +1350,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,

	/* This function manage to free the instance on failure. */
	down_write(&card->controls_rwsem);
	err = __snd_ctl_add(card, kctl);
	err = __snd_ctl_add_replace(card, kctl, CTL_ADD_EXCLUSIVE);
	if (err < 0) {
		snd_ctl_free_one(kctl);
		goto unlock;