aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/core.h2
-rw-r--r--sound/core/control.c37
-rw-r--r--sound/core/init.c1
3 files changed, 13 insertions, 27 deletions
diff --git a/include/sound/core.h b/include/sound/core.h
index 55385588eefa..357f36b5ee80 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -118,8 +118,6 @@ struct snd_card {
118 int user_ctl_count; /* count of all user controls */ 118 int user_ctl_count; /* count of all user controls */
119 struct list_head controls; /* all controls for this card */ 119 struct list_head controls; /* all controls for this card */
120 struct list_head ctl_files; /* active control files */ 120 struct list_head ctl_files; /* active control files */
121 struct mutex user_ctl_lock; /* protects user controls against
122 concurrent access */
123 121
124 struct snd_info_entry *proc_root; /* root for soundcard specific files */ 122 struct snd_info_entry *proc_root; /* root for soundcard specific files */
125 struct snd_info_entry *proc_id; /* the card id */ 123 struct snd_info_entry *proc_id; /* the card id */
diff --git a/sound/core/control.c b/sound/core/control.c
index f3bd9bdba9a7..989292fe33c2 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1095,9 +1095,7 @@ static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
1095 char *src = ue->elem_data + 1095 char *src = ue->elem_data +
1096 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size; 1096 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
1097 1097
1098 mutex_lock(&ue->card->user_ctl_lock);
1099 memcpy(&ucontrol->value, src, size); 1098 memcpy(&ucontrol->value, src, size);
1100 mutex_unlock(&ue->card->user_ctl_lock);
1101 return 0; 1099 return 0;
1102} 1100}
1103 1101
@@ -1110,11 +1108,9 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
1110 char *dst = ue->elem_data + 1108 char *dst = ue->elem_data +
1111 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size; 1109 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
1112 1110
1113 mutex_lock(&ue->card->user_ctl_lock);
1114 change = memcmp(&ucontrol->value, dst, size) != 0; 1111 change = memcmp(&ucontrol->value, dst, size) != 0;
1115 if (change) 1112 if (change)
1116 memcpy(dst, &ucontrol->value, size); 1113 memcpy(dst, &ucontrol->value, size);
1117 mutex_unlock(&ue->card->user_ctl_lock);
1118 return change; 1114 return change;
1119} 1115}
1120 1116
@@ -1124,44 +1120,37 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
1124 unsigned int __user *tlv) 1120 unsigned int __user *tlv)
1125{ 1121{
1126 struct user_element *ue = kcontrol->private_data; 1122 struct user_element *ue = kcontrol->private_data;
1127 int change = 0;
1128 void *new_data;
1129 1123
1130 if (op_flag == SNDRV_CTL_TLV_OP_WRITE) { 1124 if (op_flag == SNDRV_CTL_TLV_OP_WRITE) {
1125 int change;
1126 void *new_data;
1127
1131 if (size > 1024 * 128) /* sane value */ 1128 if (size > 1024 * 128) /* sane value */
1132 return -EINVAL; 1129 return -EINVAL;
1133 1130
1134 new_data = memdup_user(tlv, size); 1131 new_data = memdup_user(tlv, size);
1135 if (IS_ERR(new_data)) 1132 if (IS_ERR(new_data))
1136 return PTR_ERR(new_data); 1133 return PTR_ERR(new_data);
1137 mutex_lock(&ue->card->user_ctl_lock);
1138 change = ue->tlv_data_size != size; 1134 change = ue->tlv_data_size != size;
1139 if (!change) 1135 if (!change)
1140 change = memcmp(ue->tlv_data, new_data, size); 1136 change = memcmp(ue->tlv_data, new_data, size);
1141 kfree(ue->tlv_data); 1137 kfree(ue->tlv_data);
1142 ue->tlv_data = new_data; 1138 ue->tlv_data = new_data;
1143 ue->tlv_data_size = size; 1139 ue->tlv_data_size = size;
1144 mutex_unlock(&ue->card->user_ctl_lock); 1140
1141 return change;
1145 } else { 1142 } else {
1146 int ret = 0; 1143 if (!ue->tlv_data_size || !ue->tlv_data)
1144 return -ENXIO;
1145
1146 if (size < ue->tlv_data_size)
1147 return -ENOSPC;
1147 1148
1148 mutex_lock(&ue->card->user_ctl_lock);
1149 if (!ue->tlv_data_size || !ue->tlv_data) {
1150 ret = -ENXIO;
1151 goto err_unlock;
1152 }
1153 if (size < ue->tlv_data_size) {
1154 ret = -ENOSPC;
1155 goto err_unlock;
1156 }
1157 if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size)) 1149 if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
1158 ret = -EFAULT; 1150 return -EFAULT;
1159err_unlock: 1151
1160 mutex_unlock(&ue->card->user_ctl_lock); 1152 return 0;
1161 if (ret)
1162 return ret;
1163 } 1153 }
1164 return change;
1165} 1154}
1166 1155
1167static int snd_ctl_elem_init_enum_names(struct user_element *ue) 1156static int snd_ctl_elem_init_enum_names(struct user_element *ue)
diff --git a/sound/core/init.c b/sound/core/init.c
index b4365bcf28a7..6e219dc23f96 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -248,7 +248,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
248 INIT_LIST_HEAD(&card->devices); 248 INIT_LIST_HEAD(&card->devices);
249 init_rwsem(&card->controls_rwsem); 249 init_rwsem(&card->controls_rwsem);
250 rwlock_init(&card->ctl_files_rwlock); 250 rwlock_init(&card->ctl_files_rwlock);
251 mutex_init(&card->user_ctl_lock);
252 INIT_LIST_HEAD(&card->controls); 251 INIT_LIST_HEAD(&card->controls);
253 INIT_LIST_HEAD(&card->ctl_files); 252 INIT_LIST_HEAD(&card->ctl_files);
254 spin_lock_init(&card->files_lock); 253 spin_lock_init(&card->files_lock);