diff options
Diffstat (limited to 'drivers/media/video/tm6000')
-rw-r--r-- | drivers/media/video/tm6000/tm6000-video.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c index f7034df94e0a..45ed59cb2d04 100644 --- a/drivers/media/video/tm6000/tm6000-video.c +++ b/drivers/media/video/tm6000/tm6000-video.c @@ -1448,7 +1448,7 @@ static int radio_queryctrl(struct file *file, void *priv, File operations for the device ------------------------------------------------------------------*/ -static int tm6000_open(struct file *file) +static int __tm6000_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct tm6000_core *dev = video_drvdata(file); @@ -1540,23 +1540,41 @@ static int tm6000_open(struct file *file) return 0; } +static int tm6000_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + int res; + + mutex_lock(vdev->lock); + res = __tm6000_open(file); + mutex_unlock(vdev->lock); + return res; +} + static ssize_t tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) { - struct tm6000_fh *fh = file->private_data; + struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + int res; + if (!res_get(fh->dev, fh, true)) return -EBUSY; - return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, file->f_flags & O_NONBLOCK); + mutex_unlock(&dev->lock); + return res; } return 0; } static unsigned int -tm6000_poll(struct file *file, struct poll_table_struct *wait) +__tm6000_poll(struct file *file, struct poll_table_struct *wait) { struct tm6000_fh *fh = file->private_data; struct tm6000_buffer *buf; @@ -1583,6 +1601,18 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait) return 0; } +static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait) +{ + struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; + unsigned int res; + + mutex_lock(&dev->lock); + res = __tm6000_poll(file, wait); + mutex_unlock(&dev->lock); + return res; +} + static int tm6000_release(struct file *file) { struct tm6000_fh *fh = file->private_data; @@ -1592,6 +1622,7 @@ static int tm6000_release(struct file *file) dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n", video_device_node_name(vdev), dev->users); + mutex_lock(&dev->lock); dev->users--; res_free(dev, fh); @@ -1619,6 +1650,7 @@ static int tm6000_release(struct file *file) } kfree(fh); + mutex_unlock(&dev->lock); return 0; } @@ -1626,8 +1658,14 @@ static int tm6000_release(struct file *file) static int tm6000_mmap(struct file *file, struct vm_area_struct * vma) { struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; + int res; - return videobuf_mmap_mapper(&fh->vb_vidq, vma); + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + res = videobuf_mmap_mapper(&fh->vb_vidq, vma); + mutex_unlock(&dev->lock); + return res; } static struct v4l2_file_operations tm6000_fops = { @@ -1724,10 +1762,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev, vfd->release = video_device_release; vfd->debug = tm6000_debug; vfd->lock = &dev->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); |