diff options
-rw-r--r-- | include/sound/core.h | 2 | ||||
-rw-r--r-- | sound/core/control.c | 37 | ||||
-rw-r--r-- | sound/core/init.c | 1 |
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; |
1159 | err_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 | ||
1167 | static int snd_ctl_elem_init_enum_names(struct user_element *ue) | 1156 | static 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); |