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;
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;
}
*
* 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;
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;
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;
}
}
}
-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,
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;
}
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)
} 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;
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);
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)
{
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;
__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);
}
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,