diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-11 09:48:11 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 09:36:26 -0400 |
commit | 9efd85dfff92d9b52675045362677064321332bf (patch) | |
tree | b6d253375d1045a402f84570fae5a6b181524cd3 | |
parent | 4ae18398008d9a7fdddc6beb2e0b85fcc9cf093d (diff) |
[media] tm6000: fix resource locking
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/staging/tm6000/tm6000-video.c | 56 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000.h | 4 |
2 files changed, 45 insertions, 15 deletions
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index 4a5fe6670fb4..cb251af895b8 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c | |||
@@ -788,25 +788,49 @@ static struct videobuf_queue_ops tm6000_video_qops = { | |||
788 | IOCTL handling | 788 | IOCTL handling |
789 | ------------------------------------------------------------------*/ | 789 | ------------------------------------------------------------------*/ |
790 | 790 | ||
791 | static int res_get(struct tm6000_core *dev, struct tm6000_fh *fh) | 791 | static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh) |
792 | { | 792 | { |
793 | /* is it free? */ | 793 | /* Is the current fh handling it? if so, that's OK */ |
794 | if (dev->resources) | 794 | if (dev->resources == fh && dev->is_res_read) |
795 | return 0; | 795 | return true; |
796 | /* it's free, grab it */ | 796 | |
797 | dev->resources =1; | 797 | return false; |
798 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); | 798 | } |
799 | return 1; | 799 | |
800 | static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh) | ||
801 | { | ||
802 | /* Is the current fh handling it? if so, that's OK */ | ||
803 | if (dev->resources == fh) | ||
804 | return true; | ||
805 | |||
806 | return false; | ||
800 | } | 807 | } |
801 | 808 | ||
802 | static int res_locked(struct tm6000_core *dev) | 809 | static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh, |
810 | bool is_res_read) | ||
803 | { | 811 | { |
804 | return (dev->resources); | 812 | /* Is the current fh handling it? if so, that's OK */ |
813 | if (dev->resources == fh && dev->is_res_read == is_res_read) | ||
814 | return true; | ||
815 | |||
816 | /* is it free? */ | ||
817 | if (dev->resources) | ||
818 | return false; | ||
819 | |||
820 | /* grab it */ | ||
821 | dev->resources = fh; | ||
822 | dev->is_res_read = is_res_read; | ||
823 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); | ||
824 | return true; | ||
805 | } | 825 | } |
806 | 826 | ||
807 | static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) | 827 | static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) |
808 | { | 828 | { |
809 | dev->resources = 0; | 829 | /* Is the current fh handling it? if so, that's OK */ |
830 | if (dev->resources != fh) | ||
831 | return; | ||
832 | |||
833 | dev->resources = NULL; | ||
810 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); | 834 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); |
811 | } | 835 | } |
812 | 836 | ||
@@ -981,7 +1005,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
981 | if (i != fh->type) | 1005 | if (i != fh->type) |
982 | return -EINVAL; | 1006 | return -EINVAL; |
983 | 1007 | ||
984 | if (!res_get(dev,fh)) | 1008 | if (!res_get(dev, fh, false)) |
985 | return -EBUSY; | 1009 | return -EBUSY; |
986 | return (videobuf_streamon(&fh->vb_vidq)); | 1010 | return (videobuf_streamon(&fh->vb_vidq)); |
987 | } | 1011 | } |
@@ -1310,7 +1334,7 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) | |||
1310 | struct tm6000_fh *fh = file->private_data; | 1334 | struct tm6000_fh *fh = file->private_data; |
1311 | 1335 | ||
1312 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1336 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1313 | if (res_locked(fh->dev)) | 1337 | if (!res_get(fh->dev, fh, true)) |
1314 | return -EBUSY; | 1338 | return -EBUSY; |
1315 | 1339 | ||
1316 | return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, | 1340 | 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 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1352 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) |
1329 | return POLLERR; | 1353 | return POLLERR; |
1330 | 1354 | ||
1331 | if (res_get(fh->dev,fh)) { | 1355 | if (!!is_res_streaming(fh->dev, fh)) |
1356 | return POLLERR; | ||
1357 | |||
1358 | if (!is_res_read(fh->dev, fh)) { | ||
1332 | /* streaming capture */ | 1359 | /* streaming capture */ |
1333 | if (list_empty(&fh->vb_vidq.stream)) | 1360 | if (list_empty(&fh->vb_vidq.stream)) |
1334 | return POLLERR; | 1361 | return POLLERR; |
@@ -1356,6 +1383,7 @@ static int tm6000_release(struct file *file) | |||
1356 | 1383 | ||
1357 | dev->users--; | 1384 | dev->users--; |
1358 | 1385 | ||
1386 | res_free(dev, fh); | ||
1359 | if (!dev->users) { | 1387 | if (!dev->users) { |
1360 | tm6000_uninit_isoc(dev); | 1388 | tm6000_uninit_isoc(dev); |
1361 | videobuf_mmap_free(&fh->vb_vidq); | 1389 | videobuf_mmap_free(&fh->vb_vidq); |
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h index 5d9dcab5c87d..a1c6ca2647ef 100644 --- a/drivers/staging/tm6000/tm6000.h +++ b/drivers/staging/tm6000/tm6000.h | |||
@@ -189,7 +189,9 @@ struct tm6000_core { | |||
189 | int users; | 189 | int users; |
190 | 190 | ||
191 | /* various device info */ | 191 | /* various device info */ |
192 | unsigned int resources; | 192 | struct tm6000_fh *resources; /* Points to fh that is streaming */ |
193 | bool is_res_read; | ||
194 | |||
193 | struct video_device *vfd; | 195 | struct video_device *vfd; |
194 | struct tm6000_dmaqueue vidq; | 196 | struct tm6000_dmaqueue vidq; |
195 | struct v4l2_device v4l2_dev; | 197 | struct v4l2_device v4l2_dev; |