X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=sound%2Fcore%2Fpcm_native.c;h=b52e89393fa399062c93b46b81f3fa84be36d591;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=f3d5de7b55acd3ee46fa01ebb2519c5ab2eac3df;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f3d5de7b5..b52e89393 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -71,8 +72,9 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); */ DEFINE_RWLOCK(snd_pcm_link_rwlock); -static DECLARE_RWSEM(snd_pcm_link_rwsem); +EXPORT_SYMBOL(snd_pcm_link_rwlock); +static DECLARE_RWSEM(snd_pcm_link_rwsem); static inline mm_segment_t snd_enter_user(void) { @@ -319,6 +321,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, 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) { @@ -344,11 +348,26 @@ out: return err; } +static int period_to_usecs(struct snd_pcm_runtime *runtime) +{ + int usecs; + + if (! runtime->rate) + return -1; /* invalid */ + + /* take 75% of period time as the deadline */ + usecs = (750000 / runtime->rate) * runtime->period_size; + usecs += ((750000 % runtime->rate) * runtime->period_size) / + runtime->rate; + + return usecs; +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime; - int err; + int err, usecs; unsigned int bits; snd_pcm_uframes_t frames; @@ -369,7 +388,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) if (!substream->oss.oss) #endif - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -EBADFD; params->rmask = ~0U; @@ -428,6 +447,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_timer_resolution_change(substream); runtime->status->state = SNDRV_PCM_STATE_SETUP; + + remove_acceptable_latency(substream->latency_id); + if ((usecs = period_to_usecs(runtime)) >= 0) + set_acceptable_latency(substream->latency_id, usecs); return 0; _error: /* hardware might be unuseable from this time, @@ -482,11 +505,12 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; } snd_pcm_stream_unlock_irq(substream); - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&substream->mmap_count)) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); runtime->status->state = SNDRV_PCM_STATE_OPEN; + remove_acceptable_latency(substream->latency_id); return result; } @@ -936,6 +960,8 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, int state) return snd_pcm_action(&snd_pcm_action_stop, substream, state); } +EXPORT_SYMBOL(snd_pcm_stop); + /** * snd_pcm_drain_done * @substream: the PCM substream @@ -1085,6 +1111,8 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream) return err; } +EXPORT_SYMBOL(snd_pcm_suspend); + /** * snd_pcm_suspend_all * @pcm: the PCM instance @@ -1114,6 +1142,8 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) return 0; } +EXPORT_SYMBOL(snd_pcm_suspend_all); + /* resume */ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) @@ -1170,7 +1200,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, substream->ffile)) >= 0) + if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); snd_power_unlock(card); return res; @@ -1198,7 +1228,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, substream->ffile); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (result < 0) goto _unlock; } @@ -1275,13 +1305,17 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream) /* * prepare ioctl */ -static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) +/* we use the second argument for updating f_flags */ +static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, + int f_flags) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->status->state == SNDRV_PCM_STATE_OPEN || + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (snd_pcm_running(substream)) return -EBUSY; + substream->f_flags = f_flags; return 0; } @@ -1310,17 +1344,26 @@ static struct action_ops snd_pcm_action_prepare = { /** * snd_pcm_prepare * @substream: the PCM substream instance + * @file: file to refer f_flags * * Prepare the PCM substream to be triggerable. */ -int snd_pcm_prepare(struct snd_pcm_substream *substream) +static int snd_pcm_prepare(struct snd_pcm_substream *substream, + struct file *file) { 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, substream->ffile)) >= 0) - res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); + if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) + res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, + substream, f_flags); snd_power_unlock(card); return res; } @@ -1331,7 +1374,7 @@ int snd_pcm_prepare(struct snd_pcm_substream *substream) static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { - if (substream->ffile->f_flags & O_NONBLOCK) + if (substream->f_flags & O_NONBLOCK) return -EAGAIN; substream->runtime->trigger_master = substream; return 0; @@ -1410,7 +1453,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, substream->ffile); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (result < 0) { snd_power_unlock(card); return result; @@ -1448,8 +1491,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) } } up_read(&snd_pcm_link_rwsem); - if (! num_drecs) - goto _error; snd_pcm_stream_lock_irq(substream); /* resume pause */ @@ -1528,12 +1569,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) runtime = substream->runtime; card = substream->pcm->card; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->status->state == SNDRV_PCM_STATE_OPEN || + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; snd_power_lock(card); if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); + result = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (result < 0) goto _unlock; } @@ -1562,7 +1604,7 @@ static struct file *snd_pcm_file_fd(int fd) file = fget(fd); if (!file) return NULL; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major) { fput(file); @@ -1973,103 +2015,103 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) return 0; } -static void snd_pcm_add_file(struct snd_pcm_str *str, - struct snd_pcm_file *pcm_file) +static void pcm_release_private(struct snd_pcm_substream *substream) { - pcm_file->next = str->files; - str->files = pcm_file; + snd_pcm_unlink(substream); } -static void snd_pcm_remove_file(struct snd_pcm_str *str, - struct snd_pcm_file *pcm_file) +void snd_pcm_release_substream(struct snd_pcm_substream *substream) { - struct snd_pcm_file * pcm_file1; - if (str->files == pcm_file) { - str->files = pcm_file->next; - } else { - pcm_file1 = str->files; - while (pcm_file1 && pcm_file1->next != pcm_file) - pcm_file1 = pcm_file1->next; - if (pcm_file1 != NULL) - pcm_file1->next = pcm_file->next; + substream->ref_count--; + if (substream->ref_count > 0) + return; + + snd_pcm_drop(substream); + if (substream->hw_opened) { + 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); } -static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) +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) { struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - struct snd_pcm_str * str; + int err; - 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) { - if (substream->ops->hw_free != NULL) - substream->ops->hw_free(substream); - substream->ops->close(substream); - substream->ffile = NULL; + err = snd_pcm_attach_substream(pcm, stream, file, &substream); + if (err < 0) + return err; + if (substream->ref_count > 1) { + *rsubstream = substream; + return 0; } - snd_pcm_remove_file(str, pcm_file); - snd_pcm_release_substream(substream); - kfree(pcm_file); + + 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; } +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) { - 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; - 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; + if (substream->ref_count == 1) { + str = substream->pstr; + substream->file = pcm_file; + substream->pcm_release = pcm_release_private; } - file->private_data = pcm_file; *rpcm_file = pcm_file; return 0; @@ -2112,7 +2154,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); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); while (1) { err = snd_pcm_open_file(file, pcm, stream, &pcm_file); if (err >= 0) @@ -2125,16 +2167,16 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) } else break; set_current_state(TASK_INTERRUPTIBLE); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); schedule(); - down(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); if (signal_pending(current)) { err = -ERESTARTSYS; break; } } remove_wait_queue(&pcm->open_wait, &wait); - up(&pcm->open_mutex); + mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; return err; @@ -2156,13 +2198,12 @@ static int snd_pcm_release(struct inode *inode, struct file *file) 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); - down(&pcm->open_mutex); - snd_pcm_release_file(pcm_file); - up(&pcm->open_mutex); + mutex_lock(&pcm->open_mutex); + snd_pcm_release_substream(substream); + kfree(pcm_file); + mutex_unlock(&pcm->open_mutex); wake_up(&pcm->open_wait); module_put(pcm->card->module); snd_card_file_remove(pcm->card, file); @@ -2480,12 +2521,8 @@ 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, +static int snd_pcm_common_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2510,7 +2547,7 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, case SNDRV_PCM_IOCTL_CHANNEL_INFO: return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: - return snd_pcm_prepare(substream); + return snd_pcm_prepare(substream, file); case SNDRV_PCM_IOCTL_RESET: return snd_pcm_reset(substream); case SNDRV_PCM_IOCTL_START: @@ -2539,12 +2576,21 @@ 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; } -static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, +static int snd_pcm_playback_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2619,19 +2665,12 @@ 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); + return snd_pcm_common_ioctl1(file, substream, cmd, arg); } -static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, +static int snd_pcm_capture_ioctl1(struct file *file, + struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { snd_assert(substream != NULL, return -ENXIO); @@ -2707,7 +2746,7 @@ static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, return result < 0 ? result : 0; } } - return snd_pcm_common_ioctl1(substream, cmd, arg); + return snd_pcm_common_ioctl1(file, substream, cmd, arg); } static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, @@ -2720,7 +2759,8 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); + return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd, + (void __user *)arg); } static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, @@ -2733,46 +2773,36 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)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; + return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd, + (void __user *)arg); } -int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) +int snd_pcm_kernel_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: - return snd_pcm_kernel_playback_ioctl(substream, cmd, arg); + result = snd_pcm_playback_ioctl1(NULL, substream, cmd, + (void __user *)arg); + break; case SNDRV_PCM_STREAM_CAPTURE: - return snd_pcm_kernel_capture_ioctl(substream, cmd, arg); + result = snd_pcm_capture_ioctl1(NULL, substream, cmd, + (void __user *)arg); + break; default: - return -EINVAL; + result = -EINVAL; + break; } + 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) { @@ -2824,8 +2854,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, return result; } -static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector, - unsigned long count, loff_t * offset) +static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) { struct snd_pcm_file *pcm_file; @@ -2836,22 +2866,22 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector, void __user **bufs; snd_pcm_uframes_t frames; - pcm_file = file->private_data; + pcm_file = iocb->ki_filp->private_data; substream = pcm_file->substream; snd_assert(substream != NULL, return -ENXIO); runtime = substream->runtime; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - if (count > 1024 || count != runtime->channels) + if (nr_segs > 1024 || nr_segs != runtime->channels) return -EINVAL; - if (!frame_aligned(runtime, _vector->iov_len)) + if (!frame_aligned(runtime, iov->iov_len)) return -EINVAL; - frames = bytes_to_samples(runtime, _vector->iov_len); - bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL); + frames = bytes_to_samples(runtime, iov->iov_len); + bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); if (bufs == NULL) return -ENOMEM; - for (i = 0; i < count; ++i) - bufs[i] = _vector[i].iov_base; + for (i = 0; i < nr_segs; ++i) + bufs[i] = iov[i].iov_base; result = snd_pcm_lib_readv(substream, bufs, frames); if (result > 0) result = frames_to_bytes(runtime, result); @@ -2859,8 +2889,8 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector, return result; } -static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, - unsigned long count, loff_t * offset) +static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; @@ -2870,7 +2900,7 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, void __user **bufs; snd_pcm_uframes_t frames; - pcm_file = file->private_data; + pcm_file = iocb->ki_filp->private_data; substream = pcm_file->substream; snd_assert(substream != NULL, result = -ENXIO; goto end); runtime = substream->runtime; @@ -2878,17 +2908,17 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, result = -EBADFD; goto end; } - if (count > 128 || count != runtime->channels || - !frame_aligned(runtime, _vector->iov_len)) { + if (nr_segs > 128 || nr_segs != runtime->channels || + !frame_aligned(runtime, iov->iov_len)) { result = -EINVAL; goto end; } - frames = bytes_to_samples(runtime, _vector->iov_len); - bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL); + frames = bytes_to_samples(runtime, iov->iov_len); + bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); if (bufs == NULL) return -ENOMEM; - for (i = 0; i < count; ++i) - bufs[i] = _vector[i].iov_base; + for (i = 0; i < nr_segs; ++i) + bufs[i] = iov[i].iov_base; result = snd_pcm_lib_writev(substream, bufs, frames); if (result > 0) result = frames_to_bytes(runtime, result); @@ -2997,7 +3027,7 @@ static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, struct page * page; if (substream == NULL) - return NOPAGE_OOM; + return NOPAGE_SIGBUS; runtime = substream->runtime; page = virt_to_page(runtime->status); get_page(page); @@ -3040,7 +3070,7 @@ static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, struct page * page; if (substream == NULL) - return NOPAGE_OOM; + return NOPAGE_SIGBUS; runtime = substream->runtime; page = virt_to_page(runtime->control); get_page(page); @@ -3101,18 +3131,18 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, size_t dma_bytes; if (substream == NULL) - return NOPAGE_OOM; + return NOPAGE_SIGBUS; runtime = substream->runtime; offset = area->vm_pgoff << PAGE_SHIFT; offset += address - area->vm_start; - snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM); + snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS); dma_bytes = PAGE_ALIGN(runtime->dma_bytes); if (offset > dma_bytes - PAGE_SIZE) return NOPAGE_SIGBUS; if (substream->ops->page) { page = substream->ops->page(substream, offset); if (! page) - return NOPAGE_OOM; + return NOPAGE_OOM; /* XXX: is this really due to OOM? */ } else { vaddr = runtime->dma_area + offset; page = virt_to_page(vaddr); @@ -3139,7 +3169,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, area->vm_ops = &snd_pcm_vm_ops_data; area->vm_private_data = substream; area->vm_flags |= VM_RESERVED; - atomic_inc(&substream->runtime->mmap_count); + atomic_inc(&substream->mmap_count); return 0; } @@ -3171,9 +3201,11 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; - atomic_inc(&substream->runtime->mmap_count); + atomic_inc(&substream->mmap_count); return 0; } + +EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); #endif /* SNDRV_PCM_INFO_MMAP */ /* @@ -3217,6 +3249,8 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, 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; @@ -3230,11 +3264,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: - if (substream->no_mmap_ctrl) + if (pcm_file->no_compat_mmap) return -ENXIO; return snd_pcm_mmap_status(substream, file, area); case SNDRV_PCM_MMAP_OFFSET_CONTROL: - if (substream->no_mmap_ctrl) + if (pcm_file->no_compat_mmap) return -ENXIO; return snd_pcm_mmap_control(substream, file, area); default: @@ -3394,7 +3428,7 @@ struct file_operations snd_pcm_f_ops[2] = { { .owner = THIS_MODULE, .write = snd_pcm_write, - .writev = snd_pcm_writev, + .aio_write = snd_pcm_aio_write, .open = snd_pcm_playback_open, .release = snd_pcm_release, .poll = snd_pcm_playback_poll, @@ -3406,7 +3440,7 @@ struct file_operations snd_pcm_f_ops[2] = { { .owner = THIS_MODULE, .read = snd_pcm_read, - .readv = snd_pcm_readv, + .aio_read = snd_pcm_aio_read, .open = snd_pcm_capture_open, .release = snd_pcm_release, .poll = snd_pcm_capture_poll,