diff --git a/include/sound/control.h b/include/sound/control.h
index 21d047f..848940c 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -32,7 +32,7 @@ typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl
 typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
 				    int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
-				    unsigned int size,
+				    unsigned int *size,
 				    unsigned int __user *tlv);
 
 enum {
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6144882..cfd1ca1 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -647,7 +647,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
 int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *ucontrol);
 int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
-	unsigned int size, unsigned int __user *tlv);
+	unsigned int *size, unsigned int __user *tlv);
 int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
diff --git a/sound/core/control.c b/sound/core/control.c
index fb096cb..485963e 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1139,7 +1139,7 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
 
 static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
 				 int op_flag,
-				 unsigned int size,
+				 unsigned int *size,
 				 unsigned int __user *tlv)
 {
 	struct user_element *ue = kcontrol->private_data;
@@ -1147,19 +1147,19 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
 	void *new_data;
 
 	if (op_flag == SNDRV_CTL_TLV_OP_WRITE) {
-		if (size > 1024 * 128)	/* sane value */
+		if (*size > 1024 * 128)	/* sane value */
 			return -EINVAL;
 
-		new_data = memdup_user(tlv, size);
+		new_data = memdup_user(tlv, *size);
 		if (IS_ERR(new_data))
 			return PTR_ERR(new_data);
 		mutex_lock(&ue->card->user_ctl_lock);
-		change = ue->tlv_data_size != size;
+		change = ue->tlv_data_size != *size;
 		if (!change)
-			change = memcmp(ue->tlv_data, new_data, size);
+			change = memcmp(ue->tlv_data, new_data, *size);
 		kfree(ue->tlv_data);
 		ue->tlv_data = new_data;
-		ue->tlv_data_size = size;
+		ue->tlv_data_size = *size;
 		mutex_unlock(&ue->card->user_ctl_lock);
 	} else {
 		int ret = 0;
@@ -1169,12 +1169,13 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
 			ret = -ENXIO;
 			goto err_unlock;
 		}
-		if (size < ue->tlv_data_size) {
+		if (*size < ue->tlv_data_size) {
 			ret = -ENOSPC;
 			goto err_unlock;
 		}
 		if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
 			ret = -EFAULT;
+		*size = ue->tlv_data_size;
 err_unlock:
 		mutex_unlock(&ue->card->user_ctl_lock);
 		if (ret)
@@ -1466,7 +1467,15 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
 			err = -EPERM;
 			goto __kctl_end;
 		}
-		err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+		len = tlv.length;
+		err = kctl->tlv.c(kctl, op_flag, &len, _tlv->tlv);
+		if (err < 0)
+			goto __kctl_end;
+		/* Return operated bytes. */
+		if (put_user(len, &_tlv->length)) {
+			err = -EFAULT;
+			goto __kctl_end;
+		}
 		if (err > 0) {
 			struct snd_ctl_elem_id id = kctl->id;
 			up_read(&card->controls_rwsem);
@@ -1483,7 +1492,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
 			err = -ENOMEM;
 			goto __kctl_end;
 		}
-		if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
+		if (copy_to_user(_tlv->tlv, kctl->tlv.p, len) ||
+		    put_user(len, &_tlv->length))
 			err = -EFAULT;
 	}
       __kctl_end:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index bb12615..dfc84ab 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2516,7 +2516,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
  * expands the pre-defined channel maps in a form of TLV
  */
 static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			     unsigned int size, unsigned int __user *tlv)
+			     unsigned int *size, unsigned int __user *tlv)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 	const struct snd_pcm_chmap_elem *map;
@@ -2525,27 +2525,27 @@ static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 
 	if (snd_BUG_ON(!info->chmap))
 		return -EINVAL;
-	if (size < 8)
+	if (*size < 8)
 		return -ENOMEM;
 	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
 		return -EFAULT;
-	size -= 8;
+	*size -= 8;
 	dst = tlv + 2;
 	for (map = info->chmap; map->channels; map++) {
 		int chs_bytes = map->channels * 4;
 		if (!valid_chmap_channels(info, map->channels))
 			continue;
-		if (size < 8)
+		if (*size < 8)
 			return -ENOMEM;
 		if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
 		    put_user(chs_bytes, dst + 1))
 			return -EFAULT;
 		dst += 2;
-		size -= 8;
+		*size -= 8;
 		count += 8;
-		if (size < chs_bytes)
+		if (*size < chs_bytes)
 			return -ENOMEM;
-		size -= chs_bytes;
+		*size -= chs_bytes;
 		count += chs_bytes;
 		for (c = 0; c < map->channels; c++) {
 			if (put_user(map->map[c], dst))
@@ -2555,6 +2555,7 @@ static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	}
 	if (put_user(count, tlv + 1))
 		return -EFAULT;
+	*size = count + sizeof(unsigned int) * 2;
 	return 0;
 }
 
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 6c58e6f..03f4681 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -220,7 +220,7 @@ static int slave_put(struct snd_kcontrol *kcontrol,
 }
 
 static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
-			 int op_flag, unsigned int size,
+			 int op_flag, unsigned int *size,
 			 unsigned int __user *tlv)
 {
 	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
diff --git a/sound/hda/hdmi_chmap.c b/sound/hda/hdmi_chmap.c
index 81acc20..3163387 100644
--- a/sound/hda/hdmi_chmap.c
+++ b/sound/hda/hdmi_chmap.c
@@ -661,7 +661,7 @@ static int spk_mask_from_spk_alloc(int spk_alloc)
 }
 
 static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			      unsigned int size, unsigned int __user *tlv)
+			      unsigned int *size, unsigned int __user *tlv)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 	struct hdac_chmap *chmap = info->private_data;
@@ -672,11 +672,11 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	int type;
 	int spk_alloc, spk_mask;
 
-	if (size < 8)
+	if (*size < 8)
 		return -ENOMEM;
 	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
 		return -EFAULT;
-	size -= 8;
+	*size -= 8;
 	dst = tlv + 2;
 
 	spk_alloc = chmap->ops.get_spk_alloc(chmap->hdac, pcm_idx);
@@ -703,7 +703,7 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 							chmap, cap, chs);
 			if (type < 0)
 				return -ENODEV;
-			if (size < 8)
+			if (*size < 8)
 				return -ENOMEM;
 
 			if (put_user(type, dst) ||
@@ -711,13 +711,13 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 				return -EFAULT;
 
 			dst += 2;
-			size -= 8;
+			*size -= 8;
 			count += 8;
 
-			if (size < chs_bytes)
+			if (*size < chs_bytes)
 				return -ENOMEM;
 
-			size -= chs_bytes;
+			*size -= chs_bytes;
 			count += chs_bytes;
 			chmap->ops.cea_alloc_to_tlv_chmap(chmap, cap,
 						tlv_chmap, chs);
@@ -731,6 +731,8 @@ static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	if (put_user(count, tlv + 1))
 		return -EFAULT;
 
+	*size = count + sizeof(unsigned int) * 2;
+
 	return 0;
 }
 
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 9913be8..06d87e7 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1420,7 +1420,7 @@ EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
  * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
  */
 int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			  unsigned int size, unsigned int __user *_tlv)
+			  unsigned int *size, unsigned int __user *_tlv)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
@@ -1429,7 +1429,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	bool min_mute = get_amp_min_mute(kcontrol);
 	u32 caps, val1, val2;
 
-	if (size < 4 * sizeof(unsigned int))
+	if (*size < 4 * sizeof(unsigned int))
 		return -ENOMEM;
 	caps = query_amp_caps(codec, nid, dir);
 	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
@@ -1447,6 +1447,9 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 		return -EFAULT;
 	if (put_user(val2, _tlv + 3))
 		return -EFAULT;
+
+	*size = sizeof(unsigned int) * 4;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
@@ -1737,13 +1740,14 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
 {
 	int _tlv[4];
 	const int *tlv = NULL;
+	unsigned int size = sizeof(_tlv);
 	int val = -1;
 
 	if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
 		/* FIXME: set_fs() hack for obtaining user-space TLV data */
 		mm_segment_t fs = get_fs();
 		set_fs(get_ds());
-		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
+		if (!kctl->tlv.c(kctl, 0, &size, _tlv))
 			tlv = _tlv;
 		set_fs(fs);
 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
@@ -2207,7 +2211,7 @@ EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
  * set up via HDA_BIND_VOL() macro.
  */
 int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			   unsigned int size, unsigned int __user *tlv)
+			   unsigned int *size, unsigned int __user *tlv)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct hda_bind_ctls *c;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index d0e066e..35ea160 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -113,7 +113,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
 int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol);
 int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			  unsigned int size, unsigned int __user *tlv);
+			  unsigned int *size, unsigned int __user *tlv);
 int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo);
 int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
@@ -218,7 +218,7 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
 int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol);
 int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			   unsigned int size, unsigned int __user *tlv);
+			   unsigned int *size, unsigned int __user *tlv);
 
 #define HDA_BIND_VOL(xname, bindrec) \
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 9ceb2bc..bc8f342 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -3868,7 +3868,7 @@ static int ca0132_volume_put(struct snd_kcontrol *kcontrol,
 }
 
 static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			     unsigned int size, unsigned int __user *tlv)
+			     unsigned int *size, unsigned int __user *tlv)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct ca0132_spec *spec = codec->spec;
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
index e7fe15d..ee92c31 100644
--- a/sound/pci/lola/lola_mixer.c
+++ b/sound/pci/lola/lola_mixer.c
@@ -553,14 +553,14 @@ static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
 }
 
 static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			       unsigned int size, unsigned int __user *tlv)
+			       unsigned int *size, unsigned int __user *tlv)
 {
 	struct lola *chip = snd_kcontrol_chip(kcontrol);
 	int dir = kcontrol->private_value;
 	unsigned int val1, val2;
 	struct lola_pin *pin;
 
-	if (size < 4 * sizeof(unsigned int))
+	if (*size < 4 * sizeof(unsigned int))
 		return -ENOMEM;
 	pin = &chip->pin[dir].pins[0];
 
@@ -577,6 +577,9 @@ static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 		return -EFAULT;
 	if (put_user(val2, tlv + 3))
 		return -EFAULT;
+
+	*size = 4 * sizeof(unsigned int);
+
 	return 0;
 }
 
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index a513a34..b2f3aa0 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -770,20 +770,21 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
 
 int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
-				unsigned int size, unsigned int __user *tlv)
+				unsigned int *size, unsigned int __user *tlv)
 {
 	struct soc_bytes_ext *params = (void *)kcontrol->private_value;
-	unsigned int count = size < params->max ? size : params->max;
 	int ret = -ENXIO;
 
+	*size = min_t(int, *size, params->max);
+
 	switch (op_flag) {
 	case SNDRV_CTL_TLV_OP_READ:
 		if (params->get)
-			ret = params->get(kcontrol, tlv, count);
+			ret = params->get(kcontrol, tlv, *size);
 		break;
 	case SNDRV_CTL_TLV_OP_WRITE:
 		if (params->put)
-			ret = params->put(kcontrol, tlv, count);
+			ret = params->put(kcontrol, tlv, *size);
 		break;
 	}
 	return ret;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 2f8c388..52a47bc 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -535,17 +535,20 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
  * TLV callback for mixer volume controls
  */
 int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			 unsigned int size, unsigned int __user *_tlv)
+			 unsigned int *size, unsigned int __user *_tlv)
 {
 	struct usb_mixer_elem_info *cval = kcontrol->private_data;
 	DECLARE_TLV_DB_MINMAX(scale, 0, 0);
 
-	if (size < sizeof(scale))
+	if (*size < sizeof(scale))
 		return -ENOMEM;
 	scale[2] = cval->dBmin;
 	scale[3] = cval->dBmax;
 	if (copy_to_user(_tlv, scale, sizeof(scale)))
 		return -EFAULT;
+
+	*size = sizeof(scale);
+
 	return 0;
 }
 
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 3417ef3..ce4e236 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -84,7 +84,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
 				 int unitid);
 
 int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			  unsigned int size, unsigned int __user *_tlv);
+			  unsigned int *size, unsigned int __user *_tlv);
 
 #ifdef CONFIG_PM
 int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 8e9548bc..373d077 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -136,7 +136,7 @@ static bool have_dup_chmap(struct snd_usb_substream *subs,
 }
 
 static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			     unsigned int size, unsigned int __user *tlv)
+			     unsigned int *size, unsigned int __user *tlv)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 	struct snd_usb_substream *subs = info->private_data;
@@ -144,11 +144,11 @@ static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	unsigned int __user *dst;
 	int count = 0;
 
-	if (size < 8)
+	if (*size < 8)
 		return -ENOMEM;
 	if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
 		return -EFAULT;
-	size -= 8;
+	*size -= 8;
 	dst = tlv + 2;
 	list_for_each_entry(fp, &subs->fmt_list, list) {
 		int i, ch_bytes;
@@ -159,7 +159,7 @@ static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 			continue;
 		/* copy the entry */
 		ch_bytes = fp->chmap->channels * 4;
-		if (size < 8 + ch_bytes)
+		if (*size < 8 + ch_bytes)
 			return -ENOMEM;
 		if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
 		    put_user(ch_bytes, dst + 1))
@@ -171,10 +171,13 @@ static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 		}
 
 		count += 8 + ch_bytes;
-		size -= 8 + ch_bytes;
+		*size -= 8 + ch_bytes;
 	}
 	if (put_user(count, tlv + 1))
 		return -EFAULT;
+
+	*size = count + sizeof(unsigned int) * 2;
+
 	return 0;
 }
 
