diff options
Diffstat (limited to 'sound/core/init.c')
| -rw-r--r-- | sound/core/init.c | 89 | 
1 files changed, 46 insertions, 43 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c415d3..fd56afe846ed 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card)  #endif  /** - *  snd_card_new - create and initialize a soundcard structure + *  snd_card_create - create and initialize a soundcard structure   *  @idx: card index (address) [0 ... (SNDRV_CARDS-1)]   *  @xid: card identification (ASCII string)   *  @module: top level module for locking   *  @extra_size: allocate this extra size after the main soundcard structure + *  @card_ret: the pointer to store the created card instance   *   *  Creates and initializes a soundcard structure.   * - *  Returns kmallocated snd_card structure. Creates the ALSA control interface - *  (which is blocked until snd_card_register function is called). + *  The function allocates snd_card instance via kzalloc with the given + *  space for the driver to use freely.  The allocated struct is stored + *  in the given card_ret pointer. + * + *  Returns zero if successful or a negative error code.   */ -struct snd_card *snd_card_new(int idx, const char *xid, -			 struct module *module, int extra_size) +int snd_card_create(int idx, const char *xid, +		    struct module *module, int extra_size, +		    struct snd_card **card_ret)  {  	struct snd_card *card;  	int err, idx2; +	if (snd_BUG_ON(!card_ret)) +		return -EINVAL; +	*card_ret = NULL; +  	if (extra_size < 0)  		extra_size = 0;  	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); -	if (card == NULL) -		return NULL; +	if (!card) +		return -ENOMEM;  	if (xid) { -		if (!snd_info_check_reserved_words(xid)) +		if (!snd_info_check_reserved_words(xid)) { +			snd_printk(KERN_ERR +				   "given id string '%s' is reserved.\n", xid); +			err = -EBUSY;  			goto __error; +		}  		strlcpy(card->id, xid, sizeof(card->id));  	}  	err = 0; @@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,  	INIT_LIST_HEAD(&card->controls);  	INIT_LIST_HEAD(&card->ctl_files);  	spin_lock_init(&card->files_lock); +	INIT_LIST_HEAD(&card->files_list);  	init_waitqueue_head(&card->shutdown_sleep);  #ifdef CONFIG_PM  	mutex_init(&card->power_lock); @@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid,  #endif  	/* the control interface cannot be accessed from the user space until */  	/* snd_cards_bitmask and snd_cards are set with snd_card_register */ -	if ((err = snd_ctl_create(card)) < 0) { -		snd_printd("unable to register control minors\n"); +	err = snd_ctl_create(card); +	if (err < 0) { +		snd_printk(KERN_ERR "unable to register control minors\n");  		goto __error;  	} -	if ((err = snd_info_card_create(card)) < 0) { -		snd_printd("unable to create card info\n"); +	err = snd_info_card_create(card); +	if (err < 0) { +		snd_printk(KERN_ERR "unable to create card info\n");  		goto __error_ctl;  	}  	if (extra_size > 0)  		card->private_data = (char *)card + sizeof(struct snd_card); -	return card; +	*card_ret = card; +	return 0;        __error_ctl:  	snd_device_free_all(card, SNDRV_DEV_CMD_PRE);        __error:  	kfree(card); -      	return NULL; +  	return err;  } - -EXPORT_SYMBOL(snd_card_new); +EXPORT_SYMBOL(snd_card_create);  /* return non-zero if a card is already locked */  int snd_card_locked(int card) @@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)  	list_for_each_entry(_df, &shutdown_files, shutdown_list) {  		if (_df->file == file) {  			df = _df; +			list_del_init(&df->shutdown_list);  			break;  		}  	} @@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card)  	/* phase 2: replace file->f_op with special dummy operations */  	spin_lock(&card->files_lock); -	mfile = card->files; -	while (mfile) { +	list_for_each_entry(mfile, &card->files_list, list) {  		file = mfile->file;  		/* it's critical part, use endless loop */ @@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card)  		mfile->file->f_op = &snd_shutdown_f_ops;  		fops_get(mfile->file->f_op); -		 -		mfile = mfile->next;  	}  	spin_unlock(&card->files_lock);	 @@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card)  		return ret;  	spin_lock(&card->files_lock); -	if (card->files == NULL) +	if (list_empty(&card->files_list))  		free_now = 1;  	else  		card->free_on_last_close = 1; @@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card)  		return ret;  	/* wait, until all devices are ready for the free operation */ -	wait_event(card->shutdown_sleep, card->files == NULL); +	wait_event(card->shutdown_sleep, list_empty(&card->files_list));  	snd_card_do_free(card);  	return 0;  } @@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file)  		return -ENOMEM;  	mfile->file = file;  	mfile->disconnected_f_op = NULL; -	mfile->next = NULL;  	spin_lock(&card->files_lock);  	if (card->shutdown) {  		spin_unlock(&card->files_lock);  		kfree(mfile);  		return -ENODEV;  	} -	mfile->next = card->files; -	card->files = mfile; +	list_add(&mfile->list, &card->files_list);  	spin_unlock(&card->files_lock);  	return 0;  } @@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add);   */  int snd_card_file_remove(struct snd_card *card, struct file *file)  { -	struct snd_monitor_file *mfile, *pfile = NULL; +	struct snd_monitor_file *mfile, *found = NULL;  	int last_close = 0;  	spin_lock(&card->files_lock); -	mfile = card->files; -	while (mfile) { +	list_for_each_entry(mfile, &card->files_list, list) {  		if (mfile->file == file) { -			if (pfile) -				pfile->next = mfile->next; -			else -				card->files = mfile->next; +			list_del(&mfile->list); +			if (mfile->disconnected_f_op) +				fops_put(mfile->disconnected_f_op); +			found = mfile;  			break;  		} -		pfile = mfile; -		mfile = mfile->next; -	} -	if (mfile && mfile->disconnected_f_op) { -		fops_put(mfile->disconnected_f_op); -		spin_lock(&shutdown_lock); -		list_del(&mfile->shutdown_list); -		spin_unlock(&shutdown_lock);  	} -	if (card->files == NULL) +	if (list_empty(&card->files_list))  		last_close = 1;  	spin_unlock(&card->files_lock);  	if (last_close) { @@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)  		if (card->free_on_last_close)  			snd_card_do_free(card);  	} -	if (!mfile) { +	if (!found) {  		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);  		return -ENOENT;  	} -	kfree(mfile); +	kfree(found);  	return 0;  }  | 
