*
*/
-rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(snd_pcm_link_rwlock);
static DECLARE_RWSEM(snd_pcm_link_rwsem);
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;
}
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) {
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)))
*/
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;
}
/**
/* 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;
}
}
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:
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,
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;
}
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;
}
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);
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
*/
.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,
};
.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,
};