Commit 9efd85df authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] tm6000: fix resource locking

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4ae18398
...@@ -788,25 +788,49 @@ static struct videobuf_queue_ops tm6000_video_qops = { ...@@ -788,25 +788,49 @@ static struct videobuf_queue_ops tm6000_video_qops = {
IOCTL handling IOCTL handling
------------------------------------------------------------------*/ ------------------------------------------------------------------*/
static int res_get(struct tm6000_core *dev, struct tm6000_fh *fh) static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
{ {
/* is it free? */ /* Is the current fh handling it? if so, that's OK */
if (dev->resources) if (dev->resources == fh && dev->is_res_read)
return 0; return true;
/* it's free, grab it */
dev->resources =1; return false;
dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); }
return 1;
static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
{
/* Is the current fh handling it? if so, that's OK */
if (dev->resources == fh)
return true;
return false;
} }
static int res_locked(struct tm6000_core *dev) static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
bool is_res_read)
{ {
return (dev->resources); /* Is the current fh handling it? if so, that's OK */
if (dev->resources == fh && dev->is_res_read == is_res_read)
return true;
/* is it free? */
if (dev->resources)
return false;
/* grab it */
dev->resources = fh;
dev->is_res_read = is_res_read;
dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
return true;
} }
static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
{ {
dev->resources = 0; /* Is the current fh handling it? if so, that's OK */
if (dev->resources != fh)
return;
dev->resources = NULL;
dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
} }
...@@ -981,7 +1005,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) ...@@ -981,7 +1005,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
if (i != fh->type) if (i != fh->type)
return -EINVAL; return -EINVAL;
if (!res_get(dev,fh)) if (!res_get(dev, fh, false))
return -EBUSY; return -EBUSY;
return (videobuf_streamon(&fh->vb_vidq)); return (videobuf_streamon(&fh->vb_vidq));
} }
...@@ -1310,7 +1334,7 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) ...@@ -1310,7 +1334,7 @@ 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;
if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
if (res_locked(fh->dev)) if (!res_get(fh->dev, fh, true))
return -EBUSY; return -EBUSY;
return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
...@@ -1328,7 +1352,10 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait) ...@@ -1328,7 +1352,10 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
return POLLERR; return POLLERR;
if (res_get(fh->dev,fh)) { if (!!is_res_streaming(fh->dev, fh))
return POLLERR;
if (!is_res_read(fh->dev, fh)) {
/* streaming capture */ /* streaming capture */
if (list_empty(&fh->vb_vidq.stream)) if (list_empty(&fh->vb_vidq.stream))
return POLLERR; return POLLERR;
...@@ -1356,6 +1383,7 @@ static int tm6000_release(struct file *file) ...@@ -1356,6 +1383,7 @@ static int tm6000_release(struct file *file)
dev->users--; dev->users--;
res_free(dev, fh);
if (!dev->users) { if (!dev->users) {
tm6000_uninit_isoc(dev); tm6000_uninit_isoc(dev);
videobuf_mmap_free(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq);
......
...@@ -189,7 +189,9 @@ struct tm6000_core { ...@@ -189,7 +189,9 @@ struct tm6000_core {
int users; int users;
/* various device info */ /* various device info */
unsigned int resources; struct tm6000_fh *resources; /* Points to fh that is streaming */
bool is_res_read;
struct video_device *vfd; struct video_device *vfd;
struct tm6000_dmaqueue vidq; struct tm6000_dmaqueue vidq;
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment