@@ -181,6 +181,27 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
181
181
}
182
182
EXPORT_SYMBOL (snd_ctl_notify );
183
183
184
+ /**
185
+ * snd_ctl_notify_one - Send notification to user-space for a control change
186
+ * @card: the card to send notification
187
+ * @mask: the event mask, SNDRV_CTL_EVENT_*
188
+ * @kctl: the pointer with the control instance
189
+ * @ioff: the additional offset to the control index
190
+ *
191
+ * This function calls snd_ctl_notify() and does additional jobs
192
+ * like LED state changes.
193
+ */
194
+ void snd_ctl_notify_one (struct snd_card * card , unsigned int mask ,
195
+ struct snd_kcontrol * kctl , unsigned int ioff )
196
+ {
197
+ struct snd_ctl_elem_id id = kctl -> id ;
198
+
199
+ id .index += ioff ;
200
+ id .numid += ioff ;
201
+ snd_ctl_notify (card , mask , & id );
202
+ }
203
+ EXPORT_SYMBOL (snd_ctl_notify_one );
204
+
184
205
/**
185
206
* snd_ctl_new - create a new control instance with some elements
186
207
* @kctl: the pointer to store new control instance
@@ -342,7 +363,6 @@ static int __snd_ctl_add_replace(struct snd_card *card,
342
363
{
343
364
struct snd_ctl_elem_id id ;
344
365
unsigned int idx ;
345
- unsigned int count ;
346
366
struct snd_kcontrol * old ;
347
367
int err ;
348
368
@@ -376,10 +396,8 @@ static int __snd_ctl_add_replace(struct snd_card *card,
376
396
kcontrol -> id .numid = card -> last_numid + 1 ;
377
397
card -> last_numid += kcontrol -> count ;
378
398
379
- id = kcontrol -> id ;
380
- count = kcontrol -> count ;
381
- for (idx = 0 ; idx < count ; idx ++ , id .index ++ , id .numid ++ )
382
- snd_ctl_notify (card , SNDRV_CTL_EVENT_MASK_ADD , & id );
399
+ for (idx = 0 ; idx < kcontrol -> count ; idx ++ )
400
+ snd_ctl_notify_one (card , SNDRV_CTL_EVENT_MASK_ADD , kcontrol , idx );
383
401
384
402
return 0 ;
385
403
}
@@ -462,16 +480,14 @@ EXPORT_SYMBOL(snd_ctl_replace);
462
480
*/
463
481
int snd_ctl_remove (struct snd_card * card , struct snd_kcontrol * kcontrol )
464
482
{
465
- struct snd_ctl_elem_id id ;
466
483
unsigned int idx ;
467
484
468
485
if (snd_BUG_ON (!card || !kcontrol ))
469
486
return - EINVAL ;
470
487
list_del (& kcontrol -> list );
471
488
card -> controls_count -= kcontrol -> count ;
472
- id = kcontrol -> id ;
473
- for (idx = 0 ; idx < kcontrol -> count ; idx ++ , id .index ++ , id .numid ++ )
474
- snd_ctl_notify (card , SNDRV_CTL_EVENT_MASK_REMOVE , & id );
489
+ for (idx = 0 ; idx < kcontrol -> count ; idx ++ )
490
+ snd_ctl_notify_one (card , SNDRV_CTL_EVENT_MASK_REMOVE , kcontrol , idx );
475
491
snd_ctl_free_one (kcontrol );
476
492
return 0 ;
477
493
}
@@ -584,11 +600,13 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
584
600
vd -> access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
585
601
}
586
602
snd_ctl_build_ioff (id , kctl , index_offset );
587
- ret = 1 ;
603
+ downgrade_write (& card -> controls_rwsem );
604
+ snd_ctl_notify_one (card , SNDRV_CTL_EVENT_MASK_INFO , kctl , index_offset );
605
+ up_read (& card -> controls_rwsem );
606
+ return 1 ;
607
+
588
608
unlock :
589
609
up_write (& card -> controls_rwsem );
590
- if (ret > 0 )
591
- snd_ctl_notify (card , SNDRV_CTL_EVENT_MASK_INFO , id );
592
610
return ret ;
593
611
}
594
612
EXPORT_SYMBOL_GPL (snd_ctl_activate_id );
@@ -1110,25 +1128,34 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
1110
1128
unsigned int index_offset ;
1111
1129
int result ;
1112
1130
1131
+ down_write (& card -> controls_rwsem );
1113
1132
kctl = snd_ctl_find_id (card , & control -> id );
1114
- if (kctl == NULL )
1133
+ if (kctl == NULL ) {
1134
+ up_write (& card -> controls_rwsem );
1115
1135
return - ENOENT ;
1136
+ }
1116
1137
1117
1138
index_offset = snd_ctl_get_ioff (kctl , & control -> id );
1118
1139
vd = & kctl -> vd [index_offset ];
1119
1140
if (!(vd -> access & SNDRV_CTL_ELEM_ACCESS_WRITE ) || kctl -> put == NULL ||
1120
1141
(file && vd -> owner && vd -> owner != file )) {
1142
+ up_write (& card -> controls_rwsem );
1121
1143
return - EPERM ;
1122
1144
}
1123
1145
1124
1146
snd_ctl_build_ioff (& control -> id , kctl , index_offset );
1125
1147
result = kctl -> put (kctl , control );
1126
- if (result < 0 )
1148
+ if (result < 0 ) {
1149
+ up_write (& card -> controls_rwsem );
1127
1150
return result ;
1151
+ }
1128
1152
1129
1153
if (result > 0 ) {
1130
- struct snd_ctl_elem_id id = control -> id ;
1131
- snd_ctl_notify (card , SNDRV_CTL_EVENT_MASK_VALUE , & id );
1154
+ downgrade_write (& card -> controls_rwsem );
1155
+ snd_ctl_notify_one (card , SNDRV_CTL_EVENT_MASK_VALUE , kctl , index_offset );
1156
+ up_read (& card -> controls_rwsem );
1157
+ } else {
1158
+ up_write (& card -> controls_rwsem );
1132
1159
}
1133
1160
1134
1161
return 0 ;
@@ -1150,9 +1177,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
1150
1177
if (result < 0 )
1151
1178
goto error ;
1152
1179
1153
- down_write (& card -> controls_rwsem );
1154
1180
result = snd_ctl_elem_write (card , file , control );
1155
- up_write (& card -> controls_rwsem );
1156
1181
if (result < 0 )
1157
1182
goto error ;
1158
1183
@@ -1301,7 +1326,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
1301
1326
{
1302
1327
struct user_element * ue = kctl -> private_data ;
1303
1328
unsigned int * container ;
1304
- struct snd_ctl_elem_id id ;
1305
1329
unsigned int mask = 0 ;
1306
1330
int i ;
1307
1331
int change ;
@@ -1333,10 +1357,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
1333
1357
ue -> tlv_data_size = size ;
1334
1358
1335
1359
mask |= SNDRV_CTL_EVENT_MASK_TLV ;
1336
- for (i = 0 ; i < kctl -> count ; ++ i ) {
1337
- snd_ctl_build_ioff (& id , kctl , i );
1338
- snd_ctl_notify (ue -> card , mask , & id );
1339
- }
1360
+ for (i = 0 ; i < kctl -> count ; ++ i )
1361
+ snd_ctl_notify_one (ue -> card , mask , kctl , i );
1340
1362
1341
1363
return change ;
1342
1364
}
0 commit comments