diff options
| author | Takashi Iwai <tiwai@suse.de> | 2015-02-03 17:57:16 +0100 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2015-02-03 17:57:16 +0100 | 
| commit | 3fe9cf390f6dc84f76b112b0a660967a84f9a81b (patch) | |
| tree | 18b8573687ae8131db155aa791f4d2357d91e6c5 /sound/core | |
| parent | 6ccd93bdb989507717edb375d40534f1177822c5 (diff) | |
| parent | 830953c0724b42be30a74febcde6c89c706ed286 (diff) | |
| download | linux-3fe9cf390f6dc84f76b112b0a660967a84f9a81b.tar.bz2 | |
Merge branch 'topic/snd-device' into for-next
Diffstat (limited to 'sound/core')
| -rw-r--r-- | sound/core/compress_offload.c | 26 | ||||
| -rw-r--r-- | sound/core/control.c | 66 | ||||
| -rw-r--r-- | sound/core/hwdep.c | 88 | ||||
| -rw-r--r-- | sound/core/init.c | 23 | ||||
| -rw-r--r-- | sound/core/pcm.c | 70 | ||||
| -rw-r--r-- | sound/core/rawmidi.c | 47 | ||||
| -rw-r--r-- | sound/core/seq/seq_clientmgr.c | 14 | ||||
| -rw-r--r-- | sound/core/sound.c | 116 | ||||
| -rw-r--r-- | sound/core/timer.c | 42 | 
9 files changed, 237 insertions, 255 deletions
| diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 89028fab64fd..b123c42e7dc8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -868,12 +868,12 @@ static int snd_compress_dev_register(struct snd_device *device)  		return -EBADFD;  	compr = device->device_data; -	sprintf(str, "comprC%iD%i", compr->card->number, compr->device);  	pr_debug("reg %s for device %s, direction %d\n", str, compr->name,  			compr->direction);  	/* register compressed device */ -	ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, -			compr->device, &snd_compr_file_ops, compr, str); +	ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, +				  compr->card, compr->device, +				  &snd_compr_file_ops, compr, &compr->dev);  	if (ret < 0) {  		pr_err("snd_register_device failed\n %d", ret);  		return ret; @@ -887,8 +887,16 @@ static int snd_compress_dev_disconnect(struct snd_device *device)  	struct snd_compr *compr;  	compr = device->device_data; -	snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, -		compr->device); +	snd_unregister_device(&compr->dev); +	return 0; +} + +static int snd_compress_dev_free(struct snd_device *device) +{ +	struct snd_compr *compr; + +	compr = device->device_data; +	put_device(&compr->dev);  	return 0;  } @@ -903,7 +911,7 @@ int snd_compress_new(struct snd_card *card, int device,  			int dirn, struct snd_compr *compr)  {  	static struct snd_device_ops ops = { -		.dev_free = NULL, +		.dev_free = snd_compress_dev_free,  		.dev_register = snd_compress_dev_register,  		.dev_disconnect = snd_compress_dev_disconnect,  	}; @@ -911,6 +919,10 @@ int snd_compress_new(struct snd_card *card, int device,  	compr->card = card;  	compr->device = device;  	compr->direction = dirn; + +	snd_device_initialize(&compr->dev, card); +	dev_set_name(&compr->dev, "comprC%iD%i", card->number, device); +  	return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);  }  EXPORT_SYMBOL_GPL(snd_compress_new); @@ -948,7 +960,7 @@ int snd_compress_register(struct snd_compr *device)  {  	int retval; -	if (device->name == NULL || device->dev == NULL || device->ops == NULL) +	if (device->name == NULL || device->ops == NULL)  		return -EINVAL;  	pr_debug("Registering compressed device %s\n", device->name); diff --git a/sound/core/control.c b/sound/core/control.c index bb96a467e88d..60caba1f2211 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)  	unsigned long flags;  	struct snd_card *card;  	struct snd_ctl_file *ctl; -	int err; +	int i, err;  	err = nonseekable_open(inode, file);  	if (err < 0) @@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)  	init_waitqueue_head(&ctl->change_sleep);  	spin_lock_init(&ctl->read_lock);  	ctl->card = card; -	ctl->prefer_pcm_subdevice = -1; -	ctl->prefer_rawmidi_subdevice = -1; +	for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++) +		ctl->preferred_subdevice[i] = -1;  	ctl->pid = get_pid(task_pid(current));  	file->private_data = ctl;  	write_lock_irqsave(&card->ctl_files_rwlock, flags); @@ -1607,6 +1607,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)  	return fasync_helper(fd, file, on, &ctl->fasync);  } +/* return the preferred subdevice number if already assigned; + * otherwise return -1 + */ +int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type) +{ +	struct snd_ctl_file *kctl; +	int subdevice = -1; + +	read_lock(&card->ctl_files_rwlock); +	list_for_each_entry(kctl, &card->ctl_files, list) { +		if (kctl->pid == task_pid(current)) { +			subdevice = kctl->preferred_subdevice[type]; +			if (subdevice != -1) +				break; +		} +	} +	read_unlock(&card->ctl_files_rwlock); +	return subdevice; +} +EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice); +  /*   * ioctl32 compat   */ @@ -1639,19 +1660,9 @@ static const struct file_operations snd_ctl_f_ops =  static int snd_ctl_dev_register(struct snd_device *device)  {  	struct snd_card *card = device->device_data; -	int err, cardnum; -	char name[16]; -	if (snd_BUG_ON(!card)) -		return -ENXIO; -	cardnum = card->number; -	if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) -		return -ENXIO; -	sprintf(name, "controlC%i", cardnum); -	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, -				       &snd_ctl_f_ops, card, name)) < 0) -		return err; -	return 0; +	return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, +				   &snd_ctl_f_ops, card, &card->ctl_dev);  }  /* @@ -1661,13 +1672,6 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)  {  	struct snd_card *card = device->device_data;  	struct snd_ctl_file *ctl; -	int err, cardnum; - -	if (snd_BUG_ON(!card)) -		return -ENXIO; -	cardnum = card->number; -	if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) -		return -ENXIO;  	read_lock(&card->ctl_files_rwlock);  	list_for_each_entry(ctl, &card->ctl_files, list) { @@ -1676,10 +1680,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)  	}  	read_unlock(&card->ctl_files_rwlock); -	if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, -					 card, -1)) < 0) -		return err; -	return 0; +	return snd_unregister_device(&card->ctl_dev);  }  /* @@ -1696,6 +1697,7 @@ static int snd_ctl_dev_free(struct snd_device *device)  		snd_ctl_remove(card, control);  	}  	up_write(&card->controls_rwsem); +	put_device(&card->ctl_dev);  	return 0;  } @@ -1710,10 +1712,20 @@ int snd_ctl_create(struct snd_card *card)  		.dev_register =	snd_ctl_dev_register,  		.dev_disconnect = snd_ctl_dev_disconnect,  	}; +	int err;  	if (snd_BUG_ON(!card))  		return -ENXIO; -	return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); +	if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS)) +		return -ENXIO; + +	snd_device_initialize(&card->ctl_dev, card); +	dev_set_name(&card->ctl_dev, "controlC%d", card->number); + +	err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); +	if (err < 0) +		put_device(&card->ctl_dev); +	return err;  }  /* diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 69459e5f712e..84244a5143cf 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -38,7 +38,6 @@ MODULE_LICENSE("GPL");  static LIST_HEAD(snd_hwdep_devices);  static DEFINE_MUTEX(register_mutex); -static int snd_hwdep_free(struct snd_hwdep *hwdep);  static int snd_hwdep_dev_free(struct snd_device *device);  static int snd_hwdep_dev_register(struct snd_device *device);  static int snd_hwdep_dev_disconnect(struct snd_device *device); @@ -345,6 +344,11 @@ static const struct file_operations snd_hwdep_f_ops =  	.mmap =		snd_hwdep_mmap,  }; +static void release_hwdep_device(struct device *dev) +{ +	kfree(container_of(dev, struct snd_hwdep, dev)); +} +  /**   * snd_hwdep_new - create a new hwdep instance   * @card: the card instance @@ -378,48 +382,49 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,  		dev_err(card->dev, "hwdep: cannot allocate\n");  		return -ENOMEM;  	} + +	init_waitqueue_head(&hwdep->open_wait); +	mutex_init(&hwdep->open_mutex);  	hwdep->card = card;  	hwdep->device = device;  	if (id)  		strlcpy(hwdep->id, id, sizeof(hwdep->id)); + +	snd_device_initialize(&hwdep->dev, card); +	hwdep->dev.release = release_hwdep_device; +	dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device);  #ifdef CONFIG_SND_OSSEMUL  	hwdep->oss_type = -1;  #endif -	if ((err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops)) < 0) { -		snd_hwdep_free(hwdep); + +	err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops); +	if (err < 0) { +		put_device(&hwdep->dev);  		return err;  	} -	init_waitqueue_head(&hwdep->open_wait); -	mutex_init(&hwdep->open_mutex); +  	if (rhwdep)  		*rhwdep = hwdep;  	return 0;  }  EXPORT_SYMBOL(snd_hwdep_new); -static int snd_hwdep_free(struct snd_hwdep *hwdep) +static int snd_hwdep_dev_free(struct snd_device *device)  { +	struct snd_hwdep *hwdep = device->device_data;  	if (!hwdep)  		return 0;  	if (hwdep->private_free)  		hwdep->private_free(hwdep); -	kfree(hwdep); +	put_device(&hwdep->dev);  	return 0;  } -static int snd_hwdep_dev_free(struct snd_device *device) -{ -	struct snd_hwdep *hwdep = device->device_data; -	return snd_hwdep_free(hwdep); -} -  static int snd_hwdep_dev_register(struct snd_device *device)  {  	struct snd_hwdep *hwdep = device->device_data;  	struct snd_card *card = hwdep->card; -	struct device *dev;  	int err; -	char name[32];  	mutex_lock(®ister_mutex);  	if (snd_hwdep_search(card, hwdep->device)) { @@ -427,53 +432,30 @@ static int snd_hwdep_dev_register(struct snd_device *device)  		return -EBUSY;  	}  	list_add_tail(&hwdep->list, &snd_hwdep_devices); -	sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); -	dev = hwdep->dev; -	if (!dev) -		dev = snd_card_get_device_link(hwdep->card); -	err = snd_register_device_for_dev(SNDRV_DEVICE_TYPE_HWDEP, -					  hwdep->card, hwdep->device, -					  &snd_hwdep_f_ops, hwdep, name, dev); +	err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, +				  hwdep->card, hwdep->device, +				  &snd_hwdep_f_ops, hwdep, &hwdep->dev);  	if (err < 0) { -		dev_err(dev, -			"unable to register hardware dependent device %i:%i\n", -			card->number, hwdep->device); +		dev_err(&hwdep->dev, "unable to register\n");  		list_del(&hwdep->list);  		mutex_unlock(®ister_mutex);  		return err;  	} -	if (hwdep->groups) { -		struct device *d = snd_get_device(SNDRV_DEVICE_TYPE_HWDEP, -						  hwdep->card, hwdep->device); -		if (d) { -			if (hwdep->private_data) -				dev_set_drvdata(d, hwdep->private_data); -			err = sysfs_create_groups(&d->kobj, hwdep->groups); -			if (err < 0) -				dev_warn(dev, -					 "hwdep %d:%d: cannot create sysfs groups\n", -					 card->number, hwdep->device); -			put_device(d); -		} -	} -  #ifdef CONFIG_SND_OSSEMUL  	hwdep->ossreg = 0;  	if (hwdep->oss_type >= 0) { -		if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { -			dev_warn(dev, +		if (hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM && +		    hwdep->device) +			dev_warn(&hwdep->dev,  				 "only hwdep device 0 can be registered as OSS direct FM device!\n"); -		} else { -			if (snd_register_oss_device(hwdep->oss_type, -						    card, hwdep->device, -						    &snd_hwdep_f_ops, hwdep) < 0) { -				dev_err(dev, -					"unable to register OSS compatibility device %i:%i\n", -					card->number, hwdep->device); -			} else -				hwdep->ossreg = 1; -		} +		else if (snd_register_oss_device(hwdep->oss_type, +						 card, hwdep->device, +						 &snd_hwdep_f_ops, hwdep) < 0) +			dev_warn(&hwdep->dev, +				 "unable to register OSS compatibility device\n"); +		else +			hwdep->ossreg = 1;  	}  #endif  	mutex_unlock(®ister_mutex); @@ -497,7 +479,7 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)  	if (hwdep->ossreg)  		snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);  #endif -	snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); +	snd_unregister_device(&hwdep->dev);  	list_del_init(&hwdep->list);  	mutex_unlock(&hwdep->open_mutex);  	mutex_unlock(®ister_mutex); diff --git a/sound/core/init.c b/sound/core/init.c index 074875d68c15..96194599e82e 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -157,6 +157,29 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int),  	return mask; /* unchanged */  } +/* the default release callback set in snd_device_initialize() below; + * this is just NOP for now, as almost all jobs are already done in + * dev_free callback of snd_device chain instead. + */ +static void default_release(struct device *dev) +{ +} + +/** + * snd_device_initialize - Initialize struct device for sound devices + * @dev: device to initialize + * @card: card to assign, optional + */ +void snd_device_initialize(struct device *dev, struct snd_card *card) +{ +	device_initialize(dev); +	if (card) +		dev->parent = &card->card_dev; +	dev->class = sound_class; +	dev->release = default_release; +} +EXPORT_SYMBOL_GPL(snd_device_initialize); +  static int snd_card_do_free(struct snd_card *card);  static const struct attribute_group *card_dev_attr_groups[]; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index cfc56c806964..0345e53a340c 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,  			if (get_user(val, (int __user *)arg))  				return -EFAULT; -			control->prefer_pcm_subdevice = val; +			control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val;  			return 0;  		}  	} @@ -673,6 +673,8 @@ static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substrea  static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }  #endif /* CONFIG_SND_VERBOSE_PROCFS */ +static const struct attribute_group *pcm_dev_attr_groups[]; +  /**   * snd_pcm_new_stream - create a new PCM stream   * @pcm: the pcm instance @@ -698,7 +700,15 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)  	pstr->stream = stream;  	pstr->pcm = pcm;  	pstr->substream_count = substream_count; -	if (substream_count > 0 && !pcm->internal) { +	if (!substream_count) +		return 0; + +	snd_device_initialize(&pstr->dev, pcm->card); +	pstr->dev.groups = pcm_dev_attr_groups; +	dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device, +		     stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'); + +	if (!pcm->internal) {  		err = snd_pcm_stream_proc_init(pstr);  		if (err < 0) {  			pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n"); @@ -868,6 +878,8 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)  		kfree(setup);  	}  #endif +	if (pstr->substream_count) +		put_device(&pstr->dev);  }  static int snd_pcm_free(struct snd_pcm *pcm) @@ -901,9 +913,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,  	struct snd_pcm_str * pstr;  	struct snd_pcm_substream *substream;  	struct snd_pcm_runtime *runtime; -	struct snd_ctl_file *kctl;  	struct snd_card *card; -	int prefer_subdevice = -1; +	int prefer_subdevice;  	size_t size;  	if (snd_BUG_ON(!pcm || !rsubstream)) @@ -914,15 +925,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,  		return -ENODEV;  	card = pcm->card; -	read_lock(&card->ctl_files_rwlock); -	list_for_each_entry(kctl, &card->ctl_files, list) { -		if (kctl->pid == task_pid(current)) { -			prefer_subdevice = kctl->prefer_pcm_subdevice; -			if (prefer_subdevice != -1) -				break; -		} -	} -	read_unlock(&card->ctl_files_rwlock); +	prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);  	switch (stream) {  	case SNDRV_PCM_STREAM_PLAYBACK: @@ -1078,9 +1081,7 @@ static int snd_pcm_dev_register(struct snd_device *device)  	int cidx, err;  	struct snd_pcm_substream *substream;  	struct snd_pcm_notify *notify; -	char str[16];  	struct snd_pcm *pcm; -	struct device *dev;  	if (snd_BUG_ON(!device || !device->device_data))  		return -ENXIO; @@ -1097,42 +1098,22 @@ static int snd_pcm_dev_register(struct snd_device *device)  			continue;  		switch (cidx) {  		case SNDRV_PCM_STREAM_PLAYBACK: -			sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);  			devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;  			break;  		case SNDRV_PCM_STREAM_CAPTURE: -			sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);  			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;  			break;  		} -		/* device pointer to use, pcm->dev takes precedence if -		 * it is assigned, otherwise fall back to card's device -		 * if possible */ -		dev = pcm->dev; -		if (!dev) -			dev = snd_card_get_device_link(pcm->card);  		/* register pcm */ -		err = snd_register_device_for_dev(devtype, pcm->card, -						  pcm->device, -						  &snd_pcm_f_ops[cidx], -						  pcm, str, dev); +		err = snd_register_device(devtype, pcm->card, pcm->device, +					  &snd_pcm_f_ops[cidx], pcm, +					  &pcm->streams[cidx].dev);  		if (err < 0) {  			list_del(&pcm->list);  			mutex_unlock(®ister_mutex);  			return err;  		} -		dev = snd_get_device(devtype, pcm->card, pcm->device); -		if (dev) { -			err = sysfs_create_groups(&dev->kobj, -						  pcm_dev_attr_groups); -			if (err < 0) -				dev_warn(dev, -					 "pcm %d:%d: cannot create sysfs groups\n", -					 pcm->card->number, pcm->device); -			put_device(dev); -		} -  		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)  			snd_pcm_timer_init(substream);  	} @@ -1149,7 +1130,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  	struct snd_pcm *pcm = device->device_data;  	struct snd_pcm_notify *notify;  	struct snd_pcm_substream *substream; -	int cidx, devtype; +	int cidx;  	mutex_lock(®ister_mutex);  	if (list_empty(&pcm->list)) @@ -1172,16 +1153,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  		notify->n_disconnect(pcm);  	}  	for (cidx = 0; cidx < 2; cidx++) { -		devtype = -1; -		switch (cidx) { -		case SNDRV_PCM_STREAM_PLAYBACK: -			devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; -			break; -		case SNDRV_PCM_STREAM_CAPTURE: -			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; -			break; -		} -		snd_unregister_device(devtype, pcm->card, pcm->device); +		snd_unregister_device(&pcm->streams[cidx].dev);  		if (pcm->streams[cidx].chmap_kctl) {  			snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);  			pcm->streams[cidx].chmap_kctl = NULL; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6fc71a4c8a51..b5a748596fc4 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -57,11 +57,11 @@ static LIST_HEAD(snd_rawmidi_devices);  static DEFINE_MUTEX(register_mutex);  #define rmidi_err(rmidi, fmt, args...) \ -	dev_err((rmidi)->card->dev, fmt, ##args) +	dev_err(&(rmidi)->dev, fmt, ##args)  #define rmidi_warn(rmidi, fmt, args...) \ -	dev_warn((rmidi)->card->dev, fmt, ##args) +	dev_warn(&(rmidi)->dev, fmt, ##args)  #define rmidi_dbg(rmidi, fmt, args...) \ -	dev_dbg((rmidi)->card->dev, fmt, ##args) +	dev_dbg(&(rmidi)->dev, fmt, ##args)  static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)  { @@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  	struct snd_rawmidi *rmidi;  	struct snd_rawmidi_file *rawmidi_file = NULL;  	wait_queue_t wait; -	struct snd_ctl_file *kctl;  	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))   		return -EINVAL;		/* invalid combination */ @@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  	init_waitqueue_entry(&wait, current);  	add_wait_queue(&rmidi->open_wait, &wait);  	while (1) { -		subdevice = -1; -		read_lock(&card->ctl_files_rwlock); -		list_for_each_entry(kctl, &card->ctl_files, list) { -			if (kctl->pid == task_pid(current)) { -				subdevice = kctl->prefer_rawmidi_subdevice; -				if (subdevice != -1) -					break; -			} -		} -		read_unlock(&card->ctl_files_rwlock); +		subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI);  		err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);  		if (err >= 0)  			break; @@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,  		if (get_user(val, (int __user *)argp))  			return -EFAULT; -		control->prefer_rawmidi_subdevice = val; +		control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;  		return 0;  	}  	case SNDRV_CTL_IOCTL_RAWMIDI_INFO: @@ -1453,6 +1443,11 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,  	return 0;  } +static void release_rawmidi_device(struct device *dev) +{ +	kfree(container_of(dev, struct snd_rawmidi, dev)); +} +  /**   * snd_rawmidi_new - create a rawmidi instance   * @card: the card instance @@ -1497,6 +1492,11 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,  	if (id != NULL)  		strlcpy(rmidi->id, id, sizeof(rmidi->id)); + +	snd_device_initialize(&rmidi->dev, card); +	rmidi->dev.release = release_rawmidi_device; +	dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device); +  	if ((err = snd_rawmidi_alloc_substreams(rmidi,  						&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],  						SNDRV_RAWMIDI_STREAM_INPUT, @@ -1548,7 +1548,7 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi)  	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);  	if (rmidi->private_free)  		rmidi->private_free(rmidi); -	kfree(rmidi); +	put_device(&rmidi->dev);  	return 0;  } @@ -1581,19 +1581,18 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  		return -EBUSY;  	}  	list_add_tail(&rmidi->list, &snd_rawmidi_devices); -	sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); -	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, -				       rmidi->card, rmidi->device, -				       &snd_rawmidi_f_ops, rmidi, name)) < 0) { -		rmidi_err(rmidi, "unable to register rawmidi device %i:%i\n", -			  rmidi->card->number, rmidi->device); +	err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, +				  rmidi->card, rmidi->device, +				  &snd_rawmidi_f_ops, rmidi, &rmidi->dev); +	if (err < 0) { +		rmidi_err(rmidi, "unable to register\n");  		list_del(&rmidi->list);  		mutex_unlock(®ister_mutex);  		return err;  	}  	if (rmidi->ops && rmidi->ops->dev_register &&  	    (err = rmidi->ops->dev_register(rmidi)) < 0) { -		snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); +		snd_unregister_device(&rmidi->dev);  		list_del(&rmidi->list);  		mutex_unlock(®ister_mutex);  		return err; @@ -1681,7 +1680,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)  		rmidi->ossreg = 0;  	}  #endif /* CONFIG_SND_OSSEMUL */ -	snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); +	snd_unregister_device(&rmidi->dev);  	mutex_unlock(&rmidi->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 29182f56bfb7..48287651ac77 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2570,6 +2570,8 @@ static const struct file_operations snd_seq_f_ops =  	.compat_ioctl =	snd_seq_ioctl_compat,  }; +static struct device seq_dev; +  /*    * register sequencer device    */ @@ -2577,12 +2579,17 @@ int __init snd_sequencer_device_init(void)  {  	int err; +	snd_device_initialize(&seq_dev, NULL); +	dev_set_name(&seq_dev, "seq"); +  	if (mutex_lock_interruptible(®ister_mutex))  		return -ERESTARTSYS; -	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, -				       &snd_seq_f_ops, NULL, "seq")) < 0) { +	err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, +				  &snd_seq_f_ops, NULL, &seq_dev); +	if (err < 0) {  		mutex_unlock(®ister_mutex); +		put_device(&seq_dev);  		return err;  	} @@ -2598,5 +2605,6 @@ int __init snd_sequencer_device_init(void)   */  void __exit snd_sequencer_device_done(void)  { -	snd_unregister_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0); +	snd_unregister_device(&seq_dev); +	put_device(&seq_dev);  } diff --git a/sound/core/sound.c b/sound/core/sound.c index f1333060bf1c..185cec01ee25 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -242,30 +242,30 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)  #endif  /** - * snd_register_device_for_dev - Register the ALSA device file for the card + * snd_register_device - Register the ALSA device file for the card   * @type: the device type, SNDRV_DEVICE_TYPE_XXX   * @card: the card instance   * @dev: the device index   * @f_ops: the file operations   * @private_data: user pointer for f_ops->open() - * @name: the device file name - * @device: the &struct device to link this new device to + * @device: the device to register   *   * Registers an ALSA device file for the given card.   * The operators have to be set in reg parameter.   *   * Return: Zero if successful, or a negative error code on failure.   */ -int snd_register_device_for_dev(int type, struct snd_card *card, int dev, -				const struct file_operations *f_ops, -				void *private_data, -				const char *name, struct device *device) +int snd_register_device(int type, struct snd_card *card, int dev, +			const struct file_operations *f_ops, +			void *private_data, struct device *device)  {  	int minor; +	int err = 0;  	struct snd_minor *preg; -	if (snd_BUG_ON(!name)) +	if (snd_BUG_ON(!device))  		return -EINVAL; +  	preg = kmalloc(sizeof *preg, GFP_KERNEL);  	if (preg == NULL)  		return -ENOMEM; @@ -284,102 +284,56 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,  		minor = -EBUSY;  #endif  	if (minor < 0) { -		mutex_unlock(&sound_mutex); -		kfree(preg); -		return minor; -	} -	snd_minors[minor] = preg; -	preg->dev = device_create(sound_class, device, MKDEV(major, minor), -				  private_data, "%s", name); -	if (IS_ERR(preg->dev)) { -		snd_minors[minor] = NULL; -		mutex_unlock(&sound_mutex); -		minor = PTR_ERR(preg->dev); -		kfree(preg); -		return minor; +		err = minor; +		goto error;  	} -	mutex_unlock(&sound_mutex); -	return 0; -} - -EXPORT_SYMBOL(snd_register_device_for_dev); - -/* find the matching minor record - * return the index of snd_minor, or -1 if not found - */ -static int find_snd_minor(int type, struct snd_card *card, int dev) -{ -	int cardnum, minor; -	struct snd_minor *mptr; +	preg->dev = device; +	device->devt = MKDEV(major, minor); +	err = device_add(device); +	if (err < 0) +		goto error; -	cardnum = card ? card->number : -1; -	for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) -		if ((mptr = snd_minors[minor]) != NULL && -		    mptr->type == type && -		    mptr->card == cardnum && -		    mptr->device == dev) -			return minor; -	return -1; +	snd_minors[minor] = preg; + error: +	mutex_unlock(&sound_mutex); +	if (err < 0) +		kfree(preg); +	return err;  } +EXPORT_SYMBOL(snd_register_device);  /**   * snd_unregister_device - unregister the device on the given card - * @type: the device type, SNDRV_DEVICE_TYPE_XXX - * @card: the card instance - * @dev: the device index + * @dev: the device instance   *   * Unregisters the device file already registered via   * snd_register_device().   *   * Return: Zero if successful, or a negative error code on failure.   */ -int snd_unregister_device(int type, struct snd_card *card, int dev) +int snd_unregister_device(struct device *dev)  {  	int minor; +	struct snd_minor *preg;  	mutex_lock(&sound_mutex); -	minor = find_snd_minor(type, card, dev); -	if (minor < 0) { -		mutex_unlock(&sound_mutex); -		return -EINVAL; +	for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { +		preg = snd_minors[minor]; +		if (preg && preg->dev == dev) { +			snd_minors[minor] = NULL; +			device_del(dev); +			kfree(preg); +			break; +		}  	} - -	device_destroy(sound_class, MKDEV(major, minor)); - -	kfree(snd_minors[minor]); -	snd_minors[minor] = NULL;  	mutex_unlock(&sound_mutex); +	if (minor >= ARRAY_SIZE(snd_minors)) +		return -ENOENT;  	return 0;  } -  EXPORT_SYMBOL(snd_unregister_device); -/** - * snd_get_device - get the assigned device to the given type and device number - * @type: the device type, SNDRV_DEVICE_TYPE_XXX - * @card:the card instance - * @dev: the device index - * - * The caller needs to release it via put_device() after using it. - */ -struct device *snd_get_device(int type, struct snd_card *card, int dev) -{ -	int minor; -	struct device *d = NULL; - -	mutex_lock(&sound_mutex); -	minor = find_snd_minor(type, card, dev); -	if (minor >= 0) { -		d = snd_minors[minor]->dev; -		if (d) -			get_device(d); -	} -	mutex_unlock(&sound_mutex); -	return d; -} -EXPORT_SYMBOL(snd_get_device); -  #ifdef CONFIG_PROC_FS  /*   *  INFO PART diff --git a/sound/core/timer.c b/sound/core/timer.c index a44235555896..490b489d713d 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1940,6 +1940,17 @@ static const struct file_operations snd_timer_f_ops =  	.fasync = 	snd_timer_user_fasync,  }; +/* unregister the system timer */ +static void snd_timer_free_all(void) +{ +	struct snd_timer *timer, *n; + +	list_for_each_entry_safe(timer, n, &snd_timer_list, device_list) +		snd_timer_free(timer); +} + +static struct device timer_dev; +  /*   *  ENTRY functions   */ @@ -1948,30 +1959,39 @@ static int __init alsa_timer_init(void)  {  	int err; +	snd_device_initialize(&timer_dev, NULL); +	dev_set_name(&timer_dev, "timer"); +  #ifdef SNDRV_OSS_INFO_DEV_TIMERS  	snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,  			      "system timer");  #endif -	if ((err = snd_timer_register_system()) < 0) +	err = snd_timer_register_system(); +	if (err < 0) {  		pr_err("ALSA: unable to register system timer (%i)\n", err); -	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, -				       &snd_timer_f_ops, NULL, "timer")) < 0) +		put_device(&timer_dev); +		return err; +	} + +	err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, +				  &snd_timer_f_ops, NULL, &timer_dev); +	if (err < 0) {  		pr_err("ALSA: unable to register timer device (%i)\n", err); +		snd_timer_free_all(); +		put_device(&timer_dev); +		return err; +	} +  	snd_timer_proc_init();  	return 0;  }  static void __exit alsa_timer_exit(void)  { -	struct list_head *p, *n; - -	snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0); -	/* unregister the system timer */ -	list_for_each_safe(p, n, &snd_timer_list) { -		struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); -		snd_timer_free(timer); -	} +	snd_unregister_device(&timer_dev); +	snd_timer_free_all(); +	put_device(&timer_dev);  	snd_timer_proc_done();  #ifdef SNDRV_OSS_INFO_DEV_TIMERS  	snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1); |