vserver 2.0 rc7
[linux-2.6.git] / sound / core / pcm_native.c
index d051946..cad9bbd 100644 (file)
@@ -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,
 };