X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Fpcm_native.c;h=f3d5de7b55acd3ee46fa01ebb2519c5ab2eac3df;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=0860c5a84502f6f67451cdea60a566b639fdbf9b;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0860c5a84..f3d5de7b5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1170,7 +1170,7 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream) int res; snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) + if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); snd_power_unlock(card); return res; @@ -1198,7 +1198,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) snd_power_lock(card); if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); if (result < 0) goto _unlock; } @@ -1313,13 +1313,13 @@ static struct action_ops snd_pcm_action_prepare = { * * Prepare the PCM substream to be triggerable. */ -static int snd_pcm_prepare(struct snd_pcm_substream *substream) +int snd_pcm_prepare(struct snd_pcm_substream *substream) { int res; struct snd_card *card = substream->pcm->card; snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) + if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); snd_power_unlock(card); return res; @@ -1410,7 +1410,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) snd_power_lock(card); if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); if (result < 0) { snd_power_unlock(card); return result; @@ -1533,7 +1533,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) snd_power_lock(card); if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); if (result < 0) goto _unlock; } @@ -1995,65 +1995,28 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str, } } -static void pcm_release_private(struct snd_pcm_substream *substream) +static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) { - struct snd_pcm_file *pcm_file = substream->file; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + struct snd_pcm_str * str; + 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); - 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->hw_opened) { + if (substream->ffile != NULL) { if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); substream->ops->close(substream); - substream->hw_opened = 0; - } - if (substream->pcm_release) { - substream->pcm_release(substream); - substream->pcm_release = NULL; - } - 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; + substream->ffile = NULL; } - - 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_remove_file(str, pcm_file); snd_pcm_release_substream(substream); - return err; + kfree(pcm_file); + return 0; } static int snd_pcm_open_file(struct file *file, @@ -2061,29 +2024,52 @@ 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->pcm_release = pcm_release_private; + substream->no_mmap_ctrl = 0; + 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; @@ -2126,7 +2112,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) } init_waitqueue_entry(&wait, current); add_wait_queue(&pcm->open_wait, &wait); - mutex_lock(&pcm->open_mutex); + down(&pcm->open_mutex); while (1) { err = snd_pcm_open_file(file, pcm, stream, &pcm_file); if (err >= 0) @@ -2139,16 +2125,16 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) } else break; set_current_state(TASK_INTERRUPTIBLE); - mutex_unlock(&pcm->open_mutex); + up(&pcm->open_mutex); schedule(); - mutex_lock(&pcm->open_mutex); + down(&pcm->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; } } remove_wait_queue(&pcm->open_wait, &wait); - mutex_unlock(&pcm->open_mutex); + up(&pcm->open_mutex); if (err < 0) goto __error; return err; @@ -2172,10 +2158,11 @@ 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_substream(substream); - mutex_unlock(&pcm->open_mutex); + down(&pcm->open_mutex); + snd_pcm_release_file(pcm_file); + up(&pcm->open_mutex); wake_up(&pcm->open_wait); module_put(pcm->card->module); snd_card_file_remove(pcm->card, file); @@ -2493,6 +2480,11 @@ 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) { @@ -2547,14 +2539,6 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, return snd_pcm_drain(substream); case SNDRV_PCM_IOCTL_DROP: return snd_pcm_drop(substream); - case SNDRV_PCM_IOCTL_PAUSE: - { - int res; - snd_pcm_stream_lock_irq(substream); - res = snd_pcm_pause(substream, (int)(unsigned long)arg); - snd_pcm_stream_unlock_irq(substream); - return res; - } } snd_printd("unknown ioctl = 0x%x\n", cmd); return -ENOTTY; @@ -2635,6 +2619,14 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, __put_user(result, _frames); return result < 0 ? result : 0; } + case SNDRV_PCM_IOCTL_PAUSE: + { + int res; + snd_pcm_stream_lock_irq(substream); + res = snd_pcm_pause(substream, (int)(unsigned long)arg); + snd_pcm_stream_unlock_irq(substream); + return res; + } } return snd_pcm_common_ioctl1(substream, cmd, arg); } @@ -2744,28 +2736,41 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } -int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) +int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + mm_segment_t fs; + int result; + + fs = snd_enter_user(); + result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg); + snd_leave_user(fs); + return result; +} + +int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) { mm_segment_t fs; int result; fs = snd_enter_user(); + result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg); + snd_leave_user(fs); + return result; +} + +int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: - result = snd_pcm_playback_ioctl1(substream, - cmd, (void __user *)arg); - break; + return snd_pcm_kernel_playback_ioctl(substream, cmd, arg); case SNDRV_PCM_STREAM_CAPTURE: - result = snd_pcm_capture_ioctl1(substream, - cmd, (void __user *)arg); - break; + return snd_pcm_kernel_capture_ioctl(substream, cmd, arg); default: - result = -EINVAL; - break; + return -EINVAL; } - snd_leave_user(fs); - return result; } static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,