summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/sound/pcm.h12
-rw-r--r--include/sound/pcm_oss.h1
-rw-r--r--sound/core/oss/pcm_oss.c151
-rw-r--r--sound/core/pcm.c12
-rw-r--r--sound/core/pcm_lib.c49
-rw-r--r--sound/core/pcm_native.c108
6 files changed, 114 insertions, 219 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 7cf6a30c1526..66b1f08b42b9 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -369,6 +369,7 @@ struct snd_pcm_substream {
 	/* -- assigned files -- */
 	struct snd_pcm_file *file;
 	struct file *ffile;
+	void (*pcm_release)(struct snd_pcm_substream *);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
 	struct snd_pcm_oss_substream oss;
@@ -381,13 +382,10 @@ struct snd_pcm_substream {
 	struct snd_info_entry *proc_prealloc_entry;
 	/* misc flags */
 	unsigned int no_mmap_ctrl: 1;
+	unsigned int hw_opened: 1;
 };
 
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
-#else
 #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
-#endif
 
 
 struct snd_pcm_str {
@@ -468,8 +466,12 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream);
 int snd_pcm_suspend_all(struct snd_pcm *pcm);
 #endif
 int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
+			   struct snd_pcm_substream **rsubstream);
 void snd_pcm_release_substream(struct snd_pcm_substream *substream);
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
+			     struct snd_pcm_substream **rsubstream);
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
 void snd_pcm_vma_notify_data(void *client, void *data);
 int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
 
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index bff0778e1969..1d522aaa66df 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -70,7 +70,6 @@ struct snd_pcm_oss_file {
 struct snd_pcm_oss_substream {
 	unsigned oss: 1;			/* oss mode */
 	struct snd_pcm_oss_setup *setup;		/* active setup */
-	struct snd_pcm_oss_file *file;
 };
 
 struct snd_pcm_oss_stream {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 54be0bba6bd2..c056cbfe5519 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1671,6 +1671,18 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
 	return NULL;
 }
 
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime;
+	runtime = substream->runtime;
+	vfree(runtime->oss.buffer);
+	runtime->oss.buffer = NULL;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+	snd_pcm_oss_plugin_clear(substream);
+#endif
+	substream->oss.oss = 0;
+}
+
 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
 				       struct snd_pcm_oss_setup *setup,
 				       int minor)
@@ -1679,6 +1691,10 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
 
 	substream->oss.oss = 1;
 	substream->oss.setup = setup;
+	if (setup->nonblock)
+		substream->ffile->f_flags |= O_NONBLOCK;
+	else
+		substream->ffile->f_flags &= ~O_NONBLOCK;
 	runtime = substream->runtime;
 	runtime->oss.params = 1;
 	runtime->oss.trigger = 1;
@@ -1697,18 +1713,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
 	runtime->oss.fragshift = 0;
 	runtime->oss.maxfrags = 0;
 	runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime;
-	runtime = substream->runtime;
-	vfree(runtime->oss.buffer);
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-	snd_pcm_oss_plugin_clear(substream);
-#endif
-	substream->oss.file = NULL;
-	substream->oss.oss = 0;
+	substream->pcm_release = snd_pcm_oss_release_substream;
 }
 
 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1722,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
 	snd_assert(pcm_oss_file != NULL, return -ENXIO);
 	for (cidx = 0; cidx < 2; ++cidx) {
 		struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
-		struct snd_pcm_runtime *runtime;
-		if (substream == NULL)
-			continue;
-		runtime = substream->runtime;
-		
-		snd_pcm_stream_lock_irq(substream);
-		if (snd_pcm_running(substream))
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-		snd_pcm_stream_unlock_irq(substream);
-		if (substream->ffile != NULL) {
-			if (substream->ops->hw_free != NULL)
-				substream->ops->hw_free(substream);
-			substream->ops->close(substream);
-			substream->ffile = NULL;
-		}
-		snd_pcm_oss_release_substream(substream);
-		snd_pcm_release_substream(substream);
+		if (substream)
+			snd_pcm_release_substream(substream);
 	}
 	kfree(pcm_oss_file);
 	return 0;
@@ -1743,12 +1733,11 @@ static int snd_pcm_oss_open_file(struct file *file,
 				 struct snd_pcm *pcm,
 				 struct snd_pcm_oss_file **rpcm_oss_file,
 				 int minor,
-				 struct snd_pcm_oss_setup *psetup,
-				 struct snd_pcm_oss_setup *csetup)
+				 struct snd_pcm_oss_setup **setup)
 {
-	int err = 0;
+	int idx, err;
 	struct snd_pcm_oss_file *pcm_oss_file;
-	struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
+	struct snd_pcm_substream *substream;
 	unsigned int f_mode = file->f_mode;
 
 	snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1750,31 @@ static int snd_pcm_oss_open_file(struct file *file,
 	if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
 	    (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
 		f_mode = FMODE_WRITE;
-	if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
-		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-					       &psubstream)) < 0) {
+
+	for (idx = 0; idx < 2; idx++) {
+		if (! setup[idx] || setup[idx]->disable)
+			continue;
+		if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (! (f_mode & FMODE_WRITE))
+				continue;
+		} else {
+			if (! (f_mode & FMODE_READ))
+				continue;
+		}
+		err = snd_pcm_open_substream(pcm, idx, file, &substream);
+		if (err < 0) {
 			snd_pcm_oss_release_file(pcm_oss_file);
 			return err;
 		}
-		pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
-	}
-	if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
-		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 
-					       &csubstream)) < 0) {
-			if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
-				snd_pcm_oss_release_file(pcm_oss_file);
-				return err;
-			} else {
-				csubstream = NULL;
-			}
-		}
-		pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
+
+		pcm_oss_file->streams[idx] = substream;
+		snd_pcm_oss_init_substream(substream, setup[idx], minor);
 	}
 	
-	if (psubstream == NULL && csubstream == NULL) {
+	if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) {
 		snd_pcm_oss_release_file(pcm_oss_file);
 		return -EINVAL;
 	}
-	if (psubstream != NULL) {
-		psubstream->oss.file = pcm_oss_file;
-		err = snd_pcm_hw_constraints_init(psubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_init failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		if ((err = psubstream->ops->open(psubstream)) < 0) {
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		psubstream->ffile = file;
-		err = snd_pcm_hw_constraints_complete(psubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_complete failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		snd_pcm_oss_init_substream(psubstream, psetup, minor);
-	}
-	if (csubstream != NULL) {
-		csubstream->oss.file = pcm_oss_file;
-		err = snd_pcm_hw_constraints_init(csubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_init failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		if ((err = csubstream->ops->open(csubstream)) < 0) {
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		csubstream->ffile = file;
-		err = snd_pcm_hw_constraints_complete(csubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_complete failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		snd_pcm_oss_init_substream(csubstream, csetup, minor);
-	}
 
 	file->private_data = pcm_oss_file;
 	*rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1799,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
 	char task_name[32];
 	struct snd_pcm *pcm;
 	struct snd_pcm_oss_file *pcm_oss_file;
-	struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
+	struct snd_pcm_oss_setup *setup[2];
 	int nonblock;
 	wait_queue_t wait;
 
@@ -1873,23 +1820,13 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
 		err = -EFAULT;
 		goto __error;
 	}
+	memset(setup, 0, sizeof(*setup));
 	if (file->f_mode & FMODE_WRITE)
-		psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+		setup[0] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
 	if (file->f_mode & FMODE_READ)
-		csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+		setup[1] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
 
 	nonblock = !!(file->f_flags & O_NONBLOCK);
-	if (psetup && !psetup->disable) {
-		if (psetup->nonblock)
-			nonblock = 1;
-		else if (psetup->block)
-			nonblock = 0;
-	} else if (csetup && !csetup->disable) {
-		if (csetup->nonblock)
-			nonblock = 1;
-		else if (csetup->block)
-			nonblock = 0;
-	}
 	if (!nonblock)
 		nonblock = nonblock_open;
 
@@ -1898,7 +1835,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
 	mutex_lock(&pcm->open_mutex);
 	while (1) {
 		err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
-					    iminor(inode), psetup, csetup);
+					    iminor(inode), setup);
 		if (err >= 0)
 			break;
 		if (err == -EAGAIN) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 1e9878fed37f..5d7eb123b999 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data)
 	snd_pcm_tick_elapsed(substream);
 }
 
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
-			   struct snd_pcm_substream **rsubstream)
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
+			     struct file *file,
+			     struct snd_pcm_substream **rsubstream)
 {
 	struct snd_pcm_str * pstr;
 	struct snd_pcm_substream *substream;
@@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
 	*rsubstream = NULL;
 	snd_assert(pcm != NULL, return -ENXIO);
 	pstr = &pcm->streams[stream];
-	if (pstr->substream == NULL)
+	if (pstr->substream == NULL || pstr->substream_count == 0)
 		return -ENODEV;
 
 	card = pcm->card;
@@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
 	}
 	up_read(&card->controls_rwsem);
 
-	if (pstr->substream_count == 0)
-		return -ENODEV;
 	switch (stream) {
 	case SNDRV_PCM_STREAM_PLAYBACK:
 		if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
@@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
 
 	substream->runtime = runtime;
 	substream->private_data = pcm->private_data;
+	substream->ffile = file;
 	pstr->substream_opened++;
 	*rsubstream = substream;
 	return 0;
 }
 
-void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime;
 	substream->file = NULL;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eeba2f060955..230a940d00bd 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
 	    runtime->channels > 1)
@@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
@@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
@@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
-
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 13efe39e4cc6..964e4c47a7f1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1995,28 +1995,63 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
 	}
 }
 
-static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
+static void pcm_release_private(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_substream *substream;
-	struct snd_pcm_runtime *runtime;
-	struct snd_pcm_str * str;
+	struct snd_pcm_file *pcm_file = substream->file;
 
-	snd_assert(pcm_file != NULL, return -ENXIO);
-	substream = pcm_file->substream;
-	snd_assert(substream != NULL, return -ENXIO);
-	runtime = substream->runtime;
-	str = substream->pstr;
 	snd_pcm_unlink(substream);
-	if (substream->ffile != NULL) {
+	snd_pcm_remove_file(substream->pstr, pcm_file);
+	kfree(pcm_file);
+}
+
+void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+{
+	snd_pcm_drop(substream);
+	if (substream->pcm_release)
+		substream->pcm_release(substream);
+	if (substream->hw_opened) {
 		if (substream->ops->hw_free != NULL)
 			substream->ops->hw_free(substream);
 		substream->ops->close(substream);
-		substream->ffile = NULL;
+		substream->hw_opened = 0;
 	}
-	snd_pcm_remove_file(str, pcm_file);
-	snd_pcm_release_substream(substream);
-	kfree(pcm_file);
+	snd_pcm_detach_substream(substream);
+}
+
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+			   struct file *file,
+			   struct snd_pcm_substream **rsubstream)
+{
+	struct snd_pcm_substream *substream;
+	int err;
+
+	err = snd_pcm_attach_substream(pcm, stream, file, &substream);
+	if (err < 0)
+		return err;
+	substream->no_mmap_ctrl = 0;
+	err = snd_pcm_hw_constraints_init(substream);
+	if (err < 0) {
+		snd_printd("snd_pcm_hw_constraints_init failed\n");
+		goto error;
+	}
+
+	if ((err = substream->ops->open(substream)) < 0)
+		goto error;
+
+	substream->hw_opened = 1;
+
+	err = snd_pcm_hw_constraints_complete(substream);
+	if (err < 0) {
+		snd_printd("snd_pcm_hw_constraints_complete failed\n");
+		goto error;
+	}
+
+	*rsubstream = substream;
 	return 0;
+
+ error:
+	snd_pcm_release_substream(substream);
+	return err;
 }
 
 static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2059,29 @@ static int snd_pcm_open_file(struct file *file,
 			     int stream,
 			     struct snd_pcm_file **rpcm_file)
 {
-	int err = 0;
 	struct snd_pcm_file *pcm_file;
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_str *str;
+	int err;
 
 	snd_assert(rpcm_file != NULL, return -EINVAL);
 	*rpcm_file = NULL;
 
+	err = snd_pcm_open_substream(pcm, stream, file, &substream);
+	if (err < 0)
+		return err;
+
 	pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
 	if (pcm_file == NULL) {
+		snd_pcm_release_substream(substream);
 		return -ENOMEM;
 	}
-
-	if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
-		kfree(pcm_file);
-		return err;
-	}
-
 	str = substream->pstr;
 	substream->file = pcm_file;
-	substream->no_mmap_ctrl = 0;
-
+	substream->pcm_release = pcm_release_private;
 	pcm_file->substream = substream;
-
 	snd_pcm_add_file(str, pcm_file);
 
-	err = snd_pcm_hw_constraints_init(substream);
-	if (err < 0) {
-		snd_printd("snd_pcm_hw_constraints_init failed\n");
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-
-	if ((err = substream->ops->open(substream)) < 0) {
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-	substream->ffile = file;
-
-	err = snd_pcm_hw_constraints_complete(substream);
-	if (err < 0) {
-		snd_printd("snd_pcm_hw_constraints_complete failed\n");
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-
 	file->private_data = pcm_file;
 	*rpcm_file = pcm_file;
 	return 0;
@@ -2158,10 +2170,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
 	snd_assert(substream != NULL, return -ENXIO);
 	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
 	pcm = substream->pcm;
-	snd_pcm_drop(substream);
 	fasync_helper(-1, file, 0, &substream->runtime->fasync);
 	mutex_lock(&pcm->open_mutex);
-	snd_pcm_release_file(pcm_file);
+	snd_pcm_release_substream(substream);
 	mutex_unlock(&pcm->open_mutex);
 	wake_up(&pcm->open_wait);
 	module_put(pcm->card->module);
@@ -2480,11 +2491,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
 	return 0;
 }
 		
-static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
-				   unsigned int cmd, void __user *arg);
-static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
-				  unsigned int cmd, void __user *arg);
-
 static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
 				 unsigned int cmd, void __user *arg)
 {