*/
DEFINE_RWLOCK(snd_pcm_link_rwlock);
-EXPORT_SYMBOL(snd_pcm_link_rwlock);
-
static DECLARE_RWSEM(snd_pcm_link_rwsem);
+
static inline mm_segment_t snd_enter_user(void)
{
mm_segment_t fs = get_fs();
return 0;
}
-EXPORT_SYMBOL(snd_pcm_hw_refine);
-
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
if (!substream->oss.oss)
#endif
- if (atomic_read(&substream->mmap_count))
+ if (atomic_read(&runtime->mmap_count))
return -EBADFD;
params->rmask = ~0U;
return -EBADFD;
}
snd_pcm_stream_unlock_irq(substream);
- if (atomic_read(&substream->mmap_count))
+ if (atomic_read(&runtime->mmap_count))
return -EBADFD;
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
return snd_pcm_action(&snd_pcm_action_stop, substream, state);
}
-EXPORT_SYMBOL(snd_pcm_stop);
-
/**
* snd_pcm_drain_done
* @substream: the PCM substream
return err;
}
-EXPORT_SYMBOL(snd_pcm_suspend);
-
/**
* snd_pcm_suspend_all
* @pcm: the PCM instance
return 0;
}
-EXPORT_SYMBOL(snd_pcm_suspend_all);
-
/* resume */
static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
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 ioctl
*/
-/* we use the second argument for updating f_flags */
-static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
- int f_flags)
+static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (snd_pcm_running(substream))
return -EBUSY;
- substream->f_flags = f_flags;
return 0;
}
/**
* snd_pcm_prepare
* @substream: the PCM substream instance
- * @file: file to refer f_flags
*
* Prepare the PCM substream to be triggerable.
*/
-static int snd_pcm_prepare(struct snd_pcm_substream *substream,
- struct file *file)
+int snd_pcm_prepare(struct snd_pcm_substream *substream)
{
int res;
struct snd_card *card = substream->pcm->card;
- int f_flags;
-
- if (file)
- f_flags = file->f_flags;
- else
- f_flags = substream->f_flags;
snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
- res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
- substream, f_flags);
+ 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;
}
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
- if (substream->f_flags & O_NONBLOCK)
+ if (substream->ffile->f_flags & O_NONBLOCK)
return -EAGAIN;
substream->runtime->trigger_master = substream;
return 0;
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;
}
}
up_read(&snd_pcm_link_rwsem);
+ if (! num_drecs)
+ goto _error;
snd_pcm_stream_lock_irq(substream);
/* resume pause */
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)
-{
- substream->ref_count--;
- if (substream->ref_count > 0)
- return;
-
- 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;
+ substream->ffile = NULL;
}
- snd_pcm_detach_substream(substream);
+ snd_pcm_remove_file(str, pcm_file);
+ snd_pcm_release_substream(substream);
+ kfree(pcm_file);
+ return 0;
}
-EXPORT_SYMBOL(snd_pcm_release_substream);
-
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
- struct file *file,
- struct snd_pcm_substream **rsubstream)
+static int snd_pcm_open_file(struct file *file,
+ struct snd_pcm *pcm,
+ int stream,
+ struct snd_pcm_file **rpcm_file)
{
+ int err = 0;
+ struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
- int err;
+ struct snd_pcm_str *str;
- err = snd_pcm_attach_substream(pcm, stream, file, &substream);
- if (err < 0)
+ snd_assert(rpcm_file != NULL, return -EINVAL);
+ *rpcm_file = NULL;
+
+ pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
+ if (pcm_file == NULL) {
+ return -ENOMEM;
+ }
+
+ if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
+ kfree(pcm_file);
return err;
- if (substream->ref_count > 1) {
- *rsubstream = substream;
- return 0;
}
+ str = substream->pstr;
+ substream->file = pcm_file;
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");
- goto error;
+ snd_pcm_release_file(pcm_file);
+ return err;
}
- if ((err = substream->ops->open(substream)) < 0)
- goto error;
-
- substream->hw_opened = 1;
+ 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");
- goto error;
- }
-
- *rsubstream = substream;
- return 0;
-
- error:
- snd_pcm_release_substream(substream);
- return err;
-}
-
-EXPORT_SYMBOL(snd_pcm_open_substream);
-
-static int snd_pcm_open_file(struct file *file,
- struct snd_pcm *pcm,
- int stream,
- struct snd_pcm_file **rpcm_file)
-{
- 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)
+ snd_pcm_release_file(pcm_file);
return err;
-
- if (substream->ref_count > 1)
- pcm_file = substream->file;
- else {
- pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
- if (pcm_file == NULL) {
- snd_pcm_release_substream(substream);
- return -ENOMEM;
- }
- str = substream->pstr;
- substream->file = pcm_file;
- substream->pcm_release = pcm_release_private;
- pcm_file->substream = substream;
- snd_pcm_add_file(str, pcm_file);
}
+
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;
pcm_file = file->private_data;
substream = pcm_file->substream;
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_common_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
+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)
{
snd_assert(substream != NULL, return -ENXIO);
case SNDRV_PCM_IOCTL_CHANNEL_INFO:
return snd_pcm_channel_info_user(substream, arg);
case SNDRV_PCM_IOCTL_PREPARE:
- return snd_pcm_prepare(substream, file);
+ return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET:
return snd_pcm_reset(substream);
case SNDRV_PCM_IOCTL_START:
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;
}
-static int snd_pcm_playback_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
+static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_assert(substream != NULL, return -ENXIO);
__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(file, substream, cmd, arg);
+ return snd_pcm_common_ioctl1(substream, cmd, arg);
}
-static int snd_pcm_capture_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
+static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_assert(substream != NULL, return -ENXIO);
return result < 0 ? result : 0;
}
}
- return snd_pcm_common_ioctl1(file, substream, cmd, arg);
+ return snd_pcm_common_ioctl1(substream, cmd, arg);
}
static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
- return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
- (void __user *)arg);
+ return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
- return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
- (void __user *)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(NULL, 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(NULL, 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;
}
-EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
-
static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
loff_t * offset)
{
area->vm_ops = &snd_pcm_vm_ops_data;
area->vm_private_data = substream;
area->vm_flags |= VM_RESERVED;
- atomic_inc(&substream->mmap_count);
+ atomic_inc(&substream->runtime->mmap_count);
return 0;
}
(substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
size, area->vm_page_prot))
return -EAGAIN;
- atomic_inc(&substream->mmap_count);
+ atomic_inc(&substream->runtime->mmap_count);
return 0;
}
-
-EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
#endif /* SNDRV_PCM_INFO_MMAP */
/*
return snd_pcm_default_mmap(substream, area);
}
-EXPORT_SYMBOL(snd_pcm_mmap_data);
-
static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
{
struct snd_pcm_file * pcm_file;