linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / sound / core / pcm_native.c
index 0860c5a..f3d5de7 100644 (file)
@@ -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,