Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / media / video / v4l2-dev.c
index f069c61..0ca7978 100644 (file)
@@ -187,48 +187,69 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
+       int ret = -EIO;
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (!video_is_registered(vdev))
-               return -EIO;
-       return vdev->fops->read(filp, buf, sz, off);
+       if (vdev->lock)
+               mutex_lock(vdev->lock);
+       if (video_is_registered(vdev))
+               ret = vdev->fops->read(filp, buf, sz, off);
+       if (vdev->lock)
+               mutex_unlock(vdev->lock);
+       return ret;
 }
 
 static ssize_t v4l2_write(struct file *filp, const char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
+       int ret = -EIO;
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (!video_is_registered(vdev))
-               return -EIO;
-       return vdev->fops->write(filp, buf, sz, off);
+       if (vdev->lock)
+               mutex_lock(vdev->lock);
+       if (video_is_registered(vdev))
+               ret = vdev->fops->write(filp, buf, sz, off);
+       if (vdev->lock)
+               mutex_unlock(vdev->lock);
+       return ret;
 }
 
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
+       int ret = DEFAULT_POLLMASK;
 
-       if (!vdev->fops->poll || !video_is_registered(vdev))
-               return DEFAULT_POLLMASK;
-       return vdev->fops->poll(filp, poll);
+       if (!vdev->fops->poll)
+               return ret;
+       if (vdev->lock)
+               mutex_lock(vdev->lock);
+       if (video_is_registered(vdev))
+               ret = vdev->fops->poll(filp, poll);
+       if (vdev->lock)
+               mutex_unlock(vdev->lock);
+       return ret;
 }
 
 static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret;
+       int ret = -ENODEV;
 
-       if (!vdev->fops->ioctl)
-               return -ENOTTY;
        if (vdev->fops->unlocked_ioctl) {
-               ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
+               if (vdev->lock)
+                       mutex_lock(vdev->lock);
+               if (video_is_registered(vdev))
+                       ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
+               if (vdev->lock)
+                       mutex_unlock(vdev->lock);
        } else if (vdev->fops->ioctl) {
                /* TODO: convert all drivers to unlocked_ioctl */
                lock_kernel();
-               ret = vdev->fops->ioctl(filp, cmd, arg);
+               if (video_is_registered(vdev))
+                       ret = vdev->fops->ioctl(filp, cmd, arg);
                unlock_kernel();
        } else
                ret = -ENOTTY;
@@ -236,30 +257,20 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        return ret;
 }
 
-#ifdef CONFIG_MMU
-#define v4l2_get_unmapped_area NULL
-#else
-static unsigned long v4l2_get_unmapped_area(struct file *filp,
-               unsigned long addr, unsigned long len, unsigned long pgoff,
-               unsigned long flags)
-{
-       struct video_device *vdev = video_devdata(filp);
-
-       if (!vdev->fops->get_unmapped_area)
-               return -ENOSYS;
-       if (!video_is_registered(vdev))
-               return -ENODEV;
-       return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags);
-}
-#endif
-
 static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 {
        struct video_device *vdev = video_devdata(filp);
+       int ret = -ENODEV;
 
-       if (!vdev->fops->mmap || !video_is_registered(vdev))
-               return -ENODEV;
-       return vdev->fops->mmap(filp, vm);
+       if (!vdev->fops->mmap)
+               return ret;
+       if (vdev->lock)
+               mutex_lock(vdev->lock);
+       if (video_is_registered(vdev))
+               ret = vdev->fops->mmap(filp, vm);
+       if (vdev->lock)
+               mutex_unlock(vdev->lock);
+       return ret;
 }
 
 /* Override for the open function */
@@ -271,17 +282,24 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        /* Check if the video device is available */
        mutex_lock(&videodev_lock);
        vdev = video_devdata(filp);
-       /* return ENODEV if the video device has been removed
-          already or if it is not registered anymore. */
-       if (vdev == NULL || !video_is_registered(vdev)) {
+       /* return ENODEV if the video device has already been removed. */
+       if (vdev == NULL) {
                mutex_unlock(&videodev_lock);
                return -ENODEV;
        }
        /* and increase the device refcount */
        video_get(vdev);
        mutex_unlock(&videodev_lock);
-       if (vdev->fops->open)
-               ret = vdev->fops->open(filp);
+       if (vdev->fops->open) {
+               if (vdev->lock)
+                       mutex_lock(vdev->lock);
+               if (video_is_registered(vdev))
+                       ret = vdev->fops->open(filp);
+               else
+                       ret = -ENODEV;
+               if (vdev->lock)
+                       mutex_unlock(vdev->lock);
+       }
 
        /* decrease the refcount in case of an error */
        if (ret)
@@ -295,8 +313,13 @@ static int v4l2_release(struct inode *inode, struct file *filp)
        struct video_device *vdev = video_devdata(filp);
        int ret = 0;
 
-       if (vdev->fops->release)
+       if (vdev->fops->release) {
+               if (vdev->lock)
+                       mutex_lock(vdev->lock);
                vdev->fops->release(filp);
+               if (vdev->lock)
+                       mutex_unlock(vdev->lock);
+       }
 
        /* decrease the refcount unconditionally since the release()
           return value is ignored. */
@@ -309,7 +332,6 @@ static const struct file_operations v4l2_fops = {
        .read = v4l2_read,
        .write = v4l2_write,
        .open = v4l2_open,
-       .get_unmapped_area = v4l2_get_unmapped_area,
        .mmap = v4l2_mmap,
        .unlocked_ioctl = v4l2_ioctl,
 #ifdef CONFIG_COMPAT