X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Fpcm_native.c;h=cad9bbde99868049c14a1e8c7365d331308bb32c;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=d0519469c52a13026ba117e355dfcf10e7a10bb9;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index d0519469c..cad9bbde9 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn * */ -rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_pcm_link_rwlock); static DECLARE_RWSEM(snd_pcm_link_rwsem); @@ -113,10 +113,18 @@ int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info) int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t __user * _info) { - snd_pcm_info_t info; - int err = snd_pcm_info(substream, &info); - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; + snd_pcm_info_t *info; + int err; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (! info) + return -ENOMEM; + err = snd_pcm_info(substream, info); + if (err >= 0) { + if (copy_to_user(_info, info, sizeof(*info))) + err = -EFAULT; + } + kfree(info); return err; } @@ -602,17 +610,13 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t return 0; } -static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info) { - snd_pcm_channel_info_t info; snd_pcm_runtime_t *runtime; - int res; unsigned int channel; snd_assert(substream != NULL, return -ENXIO); - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - channel = info.channel; + channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { @@ -622,9 +626,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel snd_pcm_stream_unlock_irq(substream); if (channel >= runtime->channels) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.channel = channel; - res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info); + memset(info, 0, sizeof(*info)); + info->channel = channel; + return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); +} + +static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +{ + snd_pcm_channel_info_t info; + int res; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + res = snd_pcm_channel_info(substream, &info); if (res < 0) return res; if (copy_to_user(_info, &info, sizeof(info))) @@ -1032,7 +1046,13 @@ static struct action_ops snd_pcm_action_suspend = { */ int snd_pcm_suspend(snd_pcm_substream_t *substream) { - return snd_pcm_action(&snd_pcm_action_suspend, substream, 0); + int err; + unsigned long flags; + + snd_pcm_stream_lock_irqsave(substream, flags); + err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0); + snd_pcm_stream_unlock_irqrestore(substream, flags); + return err; } /** @@ -1051,11 +1071,8 @@ int snd_pcm_suspend_all(snd_pcm_t *pcm) /* FIXME: the open/close code should lock this as well */ if (substream->runtime == NULL) continue; - snd_pcm_stream_lock(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_SUSPENDED) - err = snd_pcm_suspend(substream); - snd_pcm_stream_unlock(substream); - if (err < 0) + err = snd_pcm_suspend(substream); + if (err < 0 && err != -EBUSY) return err; } } @@ -2440,7 +2457,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, case SNDRV_PCM_IOCTL_STATUS: return snd_pcm_status_user(substream, arg); case SNDRV_PCM_IOCTL_CHANNEL_INFO: - return snd_pcm_channel_info(substream, arg); + return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: return snd_pcm_prepare(substream); case SNDRV_PCM_IOCTL_RESET: @@ -2640,40 +2657,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream, return snd_pcm_common_ioctl1(substream, cmd, arg); } -static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } -static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, @@ -2683,7 +2688,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, int result; fs = snd_enter_user(); - result = snd_pcm_playback_ioctl1(substream, cmd, arg); + result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2695,7 +2700,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream, int result; fs = snd_enter_user(); - result = snd_pcm_capture_ioctl1(substream, cmd, arg); + result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -3103,8 +3108,8 @@ int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct area->vm_flags |= VM_IO; size = area->vm_end - area->vm_start; offset = area->vm_pgoff << PAGE_SHIFT; - if (io_remap_page_range(area, area->vm_start, - substream->runtime->dma_addr + offset, + if (io_remap_pfn_range(area, area->vm_start, + (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; atomic_inc(&substream->runtime->mmap_count); @@ -3197,6 +3202,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) return 0; } +/* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "pcm_compat.c" +#else +#define snd_pcm_ioctl_compat NULL +#endif + /* * To be removed helpers to keep binary compatibility */ @@ -3318,7 +3332,8 @@ static struct file_operations snd_pcm_f_ops_playback = { .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_playback_poll, - .ioctl = snd_pcm_playback_ioctl, + .unlocked_ioctl = snd_pcm_playback_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; @@ -3330,7 +3345,8 @@ static struct file_operations snd_pcm_f_ops_capture = { .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_capture_poll, - .ioctl = snd_pcm_capture_ioctl, + .unlocked_ioctl = snd_pcm_capture_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, };