static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
	int res = 0;
	struct snd_pcm_file *pcm_file;
	struct snd_pcm_substream *substream1;
	struct snd_pcm_group *group, *target_group;
	bool nonatomic = substream->pcm->nonatomic;
	struct fd f = fdget(fd);

	if (!f.file)
		return -EBADFD;
	if (!is_pcm_file(f.file)) {
		res = -EBADFD;
		goto _badf;
	}
	pcm_file = f.file->private_data;
	substream1 = pcm_file->substream;

	if (substream == substream1) {
		res = -EINVAL;
		goto _badf;
	}

	group = kzalloc(sizeof(*group), GFP_KERNEL);
	if (!group) {
		res = -ENOMEM;
		goto _nolock;
	}
	snd_pcm_group_init(group);

	down_write(&snd_pcm_link_rwsem);
	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
	    substream->runtime->status->state != substream1->runtime->status->state ||
	    substream->pcm->nonatomic != substream1->pcm->nonatomic) {
		res = -EBADFD;
		goto _end;
	}
	if (snd_pcm_stream_linked(substream1)) {
		res = -EALREADY;
		goto _end;
	}

	snd_pcm_stream_lock_irq(substream);
	if (!snd_pcm_stream_linked(substream)) {
		snd_pcm_group_assign(substream, group);
		group = NULL; /* assigned, don't free this one below */
	}
	target_group = substream->group;
	snd_pcm_stream_unlock_irq(substream);

	snd_pcm_group_lock_irq(target_group, nonatomic);
	snd_pcm_stream_lock_nested(substream1);
	snd_pcm_group_assign(substream1, target_group);
	refcount_inc(&target_group->refs);
	snd_pcm_stream_unlock(substream1);
	snd_pcm_group_unlock_irq(target_group, nonatomic);
 _end:
	up_write(&snd_pcm_link_rwsem);
 _nolock:
	kfree(group);
 _badf:
	fdput(f);
	return res;
}
static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
	int res = 0;
	struct snd_pcm_file *pcm_file;
	struct snd_pcm_substream *substream1;
	struct snd_pcm_group *group, *target_group;
	bool nonatomic = substream->pcm->nonatomic;
	struct fd f = fdget(fd);

	if (!f.file)
		return -EBADFD;
	if (!is_pcm_file(f.file)) {
		res = -EBADFD;
		goto _badf;
	}
	pcm_file = f.file->private_data;
	substream1 = pcm_file->substream;

	if (substream == substream1) {
		res = -EINVAL;
		goto _badf;
	}

	group = kzalloc(sizeof(*group), GFP_KERNEL);
	if (!group) {
		res = -ENOMEM;
		goto _nolock;
	}
	snd_pcm_group_init(group);

	down_write(&snd_pcm_link_rwsem);
	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
	    substream->runtime->status->state != substream1->runtime->status->state ||
	    substream->pcm->nonatomic != substream1->pcm->nonatomic) {
		res = -EBADFD;
		goto _end;
	}
	if (snd_pcm_stream_linked(substream1)) {
		res = -EALREADY;
		goto _end;
	}

	snd_pcm_stream_lock_irq(substream);
	if (!snd_pcm_stream_linked(substream)) {
		snd_pcm_group_assign(substream, group);
		group = NULL;  
	}
	target_group = substream->group;
	snd_pcm_stream_unlock_irq(substream);

	snd_pcm_group_lock_irq(target_group, nonatomic);
	snd_pcm_stream_lock_nested(substream1);
	snd_pcm_group_assign(substream1, target_group);
	refcount_inc(&target_group->refs);
	snd_pcm_stream_unlock(substream1);
	snd_pcm_group_unlock_irq(target_group, nonatomic);
 _end:
	up_write(&snd_pcm_link_rwsem);
 _nolock:
	kfree(group);
 _badf:
	fdput(f);
	return res;
}