@@ -133,7 +133,9 @@ void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kc
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
+int snd_ctl_add_locked(struct snd_card *card, struct snd_kcontrol *kcontrol);
int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
+int snd_ctl_remove_locked(struct snd_card *card, struct snd_kcontrol *kcontrol);
int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
@@ -39,9 +39,6 @@ static LIST_HEAD(snd_control_compat_ioctls);
#endif
static struct snd_ctl_layer_ops *snd_ctl_layer;
-static int snd_ctl_remove_locked(struct snd_card *card,
- struct snd_kcontrol *kcontrol);
-
static int snd_ctl_open(struct inode *inode, struct file *file)
{
unsigned long flags;
@@ -509,6 +506,27 @@ static int __snd_ctl_add_replace(struct snd_card *card,
return 0;
}
+static int snd_ctl_add_replace_locked(struct snd_card *card,
+ struct snd_kcontrol *kcontrol,
+ enum snd_ctl_add_mode mode)
+{
+ int err = -EINVAL;
+
+ if (! kcontrol)
+ return err;
+ if (snd_BUG_ON(!card || !kcontrol->info))
+ goto error;
+
+ err = __snd_ctl_add_replace(card, kcontrol, mode);
+ if (err < 0)
+ goto error;
+ return 0;
+
+ error:
+ snd_ctl_free_one(kcontrol);
+ return err;
+}
+
static int snd_ctl_add_replace(struct snd_card *card,
struct snd_kcontrol *kcontrol,
enum snd_ctl_add_mode mode)
@@ -532,6 +550,16 @@ static int snd_ctl_add_replace(struct snd_card *card,
return err;
}
+/**
+ * snd_ctl_add_locked - same as snd_ctl_add(), but card->controls_rwsem
+ * is expected to be already locked if necessary.
+ */
+int snd_ctl_add_locked(struct snd_card *card, struct snd_kcontrol *kcontrol)
+{
+ return snd_ctl_add_replace_locked(card, kcontrol, CTL_ADD_EXCLUSIVE);
+}
+EXPORT_SYMBOL_GPL(snd_ctl_add_locked);
+
/**
* snd_ctl_add - add the control instance to the card
* @card: the card instance
@@ -596,11 +624,16 @@ static int __snd_ctl_remove(struct snd_card *card,
return 0;
}
-static inline int snd_ctl_remove_locked(struct snd_card *card,
- struct snd_kcontrol *kcontrol)
+/**
+ * snd_ctl_remove_locked - same as snd_ctl_remove(), but card->controls_rwsem
+ * is expected to be already locked if necessary.
+ */
+int snd_ctl_remove_locked(struct snd_card *card,
+ struct snd_kcontrol *kcontrol)
{
return __snd_ctl_remove(card, kcontrol, true);
}
+EXPORT_SYMBOL_GPL(snd_ctl_remove_locked);
/**
* snd_ctl_remove - remove the control from the card and release it
This will be used to dynamically change the available controls from another control's put() callback, which is already locked. One might want to add snd_ctl_replace_locked() for completeness, but I have no use for it now. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> --- applying this upstream would simplify applying the emu10k1 high bit-rate patchset locally, as it would limit the affected modules to the driver itself. v4: - adjust to recent locking changes - mark exports as internal v3: - fixed typo in commit message v2: - extended commit message --- include/sound/control.h | 2 ++ sound/core/control.c | 43 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-)