@@ -134,6 +134,9 @@ void snd_device_initialize(struct device *dev, struct snd_card *card)
134134}
135135EXPORT_SYMBOL_GPL (snd_device_initialize );
136136
137+ static int snd_card_init (struct snd_card * card , struct device * parent ,
138+ int idx , const char * xid , struct module * module ,
139+ size_t extra_size );
137140static int snd_card_do_free (struct snd_card * card );
138141static const struct attribute_group card_dev_attr_group ;
139142
@@ -163,9 +166,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
163166{
164167 struct snd_card * card ;
165168 int err ;
166- #ifdef CONFIG_SND_DEBUG
167- char name [8 ];
168- #endif
169169
170170 if (snd_BUG_ON (!card_ret ))
171171 return - EINVAL ;
@@ -176,6 +176,74 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
176176 card = kzalloc (sizeof (* card ) + extra_size , GFP_KERNEL );
177177 if (!card )
178178 return - ENOMEM ;
179+
180+ err = snd_card_init (card , parent , idx , xid , module , extra_size );
181+ if (err < 0 ) {
182+ kfree (card );
183+ return err ;
184+ }
185+
186+ * card_ret = card ;
187+ return 0 ;
188+ }
189+ EXPORT_SYMBOL (snd_card_new );
190+
191+ static void __snd_card_release (struct device * dev , void * data )
192+ {
193+ snd_card_free (data );
194+ }
195+
196+ /**
197+ * snd_devm_card_new - managed snd_card object creation
198+ * @parent: the parent device object
199+ * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
200+ * @xid: card identification (ASCII string)
201+ * @module: top level module for locking
202+ * @extra_size: allocate this extra size after the main soundcard structure
203+ * @card_ret: the pointer to store the created card instance
204+ *
205+ * This function works like snd_card_new() but manages the allocated resource
206+ * via devres, i.e. you don't need to free explicitly.
207+ *
208+ * When a snd_card object is created with this function and registered via
209+ * snd_card_register(), the very first devres action to call snd_card_free()
210+ * is added automatically. In that way, the resource disconnection is assured
211+ * at first, then released in the expected order.
212+ */
213+ int snd_devm_card_new (struct device * parent , int idx , const char * xid ,
214+ struct module * module , size_t extra_size ,
215+ struct snd_card * * card_ret )
216+ {
217+ struct snd_card * card ;
218+ int err ;
219+
220+ * card_ret = NULL ;
221+ card = devres_alloc (__snd_card_release , sizeof (* card ) + extra_size ,
222+ GFP_KERNEL );
223+ if (!card )
224+ return - ENOMEM ;
225+ card -> managed = true;
226+ err = snd_card_init (card , parent , idx , xid , module , extra_size );
227+ if (err < 0 ) {
228+ devres_free (card );
229+ return err ;
230+ }
231+
232+ devres_add (parent , card );
233+ * card_ret = card ;
234+ return 0 ;
235+ }
236+ EXPORT_SYMBOL_GPL (snd_devm_card_new );
237+
238+ static int snd_card_init (struct snd_card * card , struct device * parent ,
239+ int idx , const char * xid , struct module * module ,
240+ size_t extra_size )
241+ {
242+ int err ;
243+ #ifdef CONFIG_SND_DEBUG
244+ char name [8 ];
245+ #endif
246+
179247 if (extra_size > 0 )
180248 card -> private_data = (char * )card + sizeof (struct snd_card );
181249 if (xid )
@@ -197,7 +265,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
197265 mutex_unlock (& snd_card_mutex );
198266 dev_err (parent , "cannot find the slot for index %d (range 0-%i), error: %d\n" ,
199267 idx , snd_ecards_limit - 1 , err );
200- kfree (card );
201268 return err ;
202269 }
203270 set_bit (idx , snd_cards_lock ); /* lock it */
@@ -256,8 +323,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
256323 sprintf (name , "card%d" , idx );
257324 card -> debugfs_root = debugfs_create_dir (name , sound_debugfs_root );
258325#endif
259-
260- * card_ret = card ;
261326 return 0 ;
262327
263328 __error_ctl :
@@ -266,7 +331,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
266331 put_device (& card -> card_dev );
267332 return err ;
268333}
269- EXPORT_SYMBOL (snd_card_new );
270334
271335/**
272336 * snd_card_ref - Get the card object from the index
@@ -481,6 +545,7 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
481545
482546static int snd_card_do_free (struct snd_card * card )
483547{
548+ card -> releasing = true;
484549#if IS_ENABLED (CONFIG_SND_MIXER_OSS )
485550 if (snd_mixer_oss_notify_callback )
486551 snd_mixer_oss_notify_callback (card , SND_MIXER_OSS_NOTIFY_FREE );
@@ -498,7 +563,8 @@ static int snd_card_do_free(struct snd_card *card)
498563#endif
499564 if (card -> release_completion )
500565 complete (card -> release_completion );
501- kfree (card );
566+ if (!card -> managed )
567+ kfree (card );
502568 return 0 ;
503569}
504570
@@ -745,6 +811,14 @@ int snd_card_add_dev_attr(struct snd_card *card,
745811}
746812EXPORT_SYMBOL_GPL (snd_card_add_dev_attr );
747813
814+ static void trigger_card_free (void * data )
815+ {
816+ struct snd_card * card = data ;
817+
818+ if (!card -> releasing )
819+ snd_card_free (data );
820+ }
821+
748822/**
749823 * snd_card_register - register the soundcard
750824 * @card: soundcard structure
@@ -768,6 +842,15 @@ int snd_card_register(struct snd_card *card)
768842 if (err < 0 )
769843 return err ;
770844 card -> registered = true;
845+ } else {
846+ if (card -> managed )
847+ devm_remove_action (card -> dev , trigger_card_free , card );
848+ }
849+
850+ if (card -> managed ) {
851+ err = devm_add_action (card -> dev , trigger_card_free , card );
852+ if (err < 0 )
853+ return err ;
771854 }
772855
773856 err = snd_device_register_all (card );
0 commit comments