@@ -181,6 +181,27 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
181181}
182182EXPORT_SYMBOL (snd_ctl_notify );
183183
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+
184205/**
185206 * snd_ctl_new - create a new control instance with some elements
186207 * @kctl: the pointer to store new control instance
@@ -342,7 +363,6 @@ static int __snd_ctl_add_replace(struct snd_card *card,
342363{
343364 struct snd_ctl_elem_id id ;
344365 unsigned int idx ;
345- unsigned int count ;
346366 struct snd_kcontrol * old ;
347367 int err ;
348368
@@ -376,10 +396,8 @@ static int __snd_ctl_add_replace(struct snd_card *card,
376396 kcontrol -> id .numid = card -> last_numid + 1 ;
377397 card -> last_numid += kcontrol -> count ;
378398
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 );
383401
384402 return 0 ;
385403}
@@ -462,16 +480,14 @@ EXPORT_SYMBOL(snd_ctl_replace);
462480 */
463481int snd_ctl_remove (struct snd_card * card , struct snd_kcontrol * kcontrol )
464482{
465- struct snd_ctl_elem_id id ;
466483 unsigned int idx ;
467484
468485 if (snd_BUG_ON (!card || !kcontrol ))
469486 return - EINVAL ;
470487 list_del (& kcontrol -> list );
471488 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 );
475491 snd_ctl_free_one (kcontrol );
476492 return 0 ;
477493}
@@ -584,11 +600,13 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
584600 vd -> access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
585601 }
586602 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+
588608 unlock :
589609 up_write (& card -> controls_rwsem );
590- if (ret > 0 )
591- snd_ctl_notify (card , SNDRV_CTL_EVENT_MASK_INFO , id );
592610 return ret ;
593611}
594612EXPORT_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,
11101128 unsigned int index_offset ;
11111129 int result ;
11121130
1131+ down_write (& card -> controls_rwsem );
11131132 kctl = snd_ctl_find_id (card , & control -> id );
1114- if (kctl == NULL )
1133+ if (kctl == NULL ) {
1134+ up_write (& card -> controls_rwsem );
11151135 return - ENOENT ;
1136+ }
11161137
11171138 index_offset = snd_ctl_get_ioff (kctl , & control -> id );
11181139 vd = & kctl -> vd [index_offset ];
11191140 if (!(vd -> access & SNDRV_CTL_ELEM_ACCESS_WRITE ) || kctl -> put == NULL ||
11201141 (file && vd -> owner && vd -> owner != file )) {
1142+ up_write (& card -> controls_rwsem );
11211143 return - EPERM ;
11221144 }
11231145
11241146 snd_ctl_build_ioff (& control -> id , kctl , index_offset );
11251147 result = kctl -> put (kctl , control );
1126- if (result < 0 )
1148+ if (result < 0 ) {
1149+ up_write (& card -> controls_rwsem );
11271150 return result ;
1151+ }
11281152
11291153 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 );
11321159 }
11331160
11341161 return 0 ;
@@ -1150,9 +1177,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
11501177 if (result < 0 )
11511178 goto error ;
11521179
1153- down_write (& card -> controls_rwsem );
11541180 result = snd_ctl_elem_write (card , file , control );
1155- up_write (& card -> controls_rwsem );
11561181 if (result < 0 )
11571182 goto error ;
11581183
@@ -1301,7 +1326,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
13011326{
13021327 struct user_element * ue = kctl -> private_data ;
13031328 unsigned int * container ;
1304- struct snd_ctl_elem_id id ;
13051329 unsigned int mask = 0 ;
13061330 int i ;
13071331 int change ;
@@ -1333,10 +1357,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
13331357 ue -> tlv_data_size = size ;
13341358
13351359 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 );
13401362
13411363 return change ;
13421364}
0 commit comments