aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2007-11-10 23:08:26 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:06 -0500
commita225452ef80a7bd894fd2dfd01a4973d444152f4 (patch)
tree397c483c75751106545ef989d83fe25a7c57347b /drivers/media/video/em28xx/em28xx-video.c
parenta3a048cea301baba5d451991074a85dc20a8f228 (diff)
V4L/DVB (6583): Fix em28xx read stream locking
On some situations, closing an streaming application and re-opening were returning -EBUSY. Uses the same locking schema also present on cx88. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c77
1 files changed, 56 insertions, 21 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 5b17ca9cad11..f0191779a8e2 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -225,6 +225,44 @@ static void video_mux(struct em28xx *dev, int index)
225 } 225 }
226} 226}
227 227
228/* Usage lock check functions */
229static int res_get(struct em28xx_fh *fh)
230{
231 struct em28xx *dev = fh->dev;
232 int rc = 0;
233
234 /* This instance already has stream_on */
235 if (fh->stream_on)
236 return rc;
237
238 mutex_lock(&dev->lock);
239
240 if (dev->stream_on)
241 rc = -EINVAL;
242 else {
243 dev->stream_on = 1;
244 fh->stream_on = 1;
245 }
246
247 mutex_unlock(&dev->lock);
248 return rc;
249}
250
251static int res_check(struct em28xx_fh *fh)
252{
253 return (fh->stream_on);
254}
255
256static void res_free(struct em28xx_fh *fh)
257{
258 struct em28xx *dev = fh->dev;
259
260 mutex_lock(&dev->lock);
261 fh->stream_on = 0;
262 dev->stream_on = 0;
263 mutex_unlock(&dev->lock);
264}
265
228/* 266/*
229 * em28xx_v4l2_open() 267 * em28xx_v4l2_open()
230 * inits the device and starts isoc transfer 268 * inits the device and starts isoc transfer
@@ -328,15 +366,16 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
328 366
329 em28xx_videodbg("users=%d\n", dev->users); 367 em28xx_videodbg("users=%d\n", dev->users);
330 368
369
370 if (res_check(fh))
371 res_free(fh);
372
331 mutex_lock(&dev->lock); 373 mutex_lock(&dev->lock);
332 if (fh->reader == 1)
333 fh->reader = 0;
334 374
335 if (dev->users == 1) { 375 if (dev->users == 1) {
336 dev->reader = 0;
337
338 em28xx_uninit_isoc(dev); 376 em28xx_uninit_isoc(dev);
339 em28xx_release_buffers(dev); 377 em28xx_release_buffers(dev);
378 dev->io = IO_NONE;
340 379
341 /* the device is already disconnect, 380 /* the device is already disconnect,
342 free the remaining resources */ 381 free the remaining resources */
@@ -377,16 +416,15 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
377 struct em28xx_fh *fh = filp->private_data; 416 struct em28xx_fh *fh = filp->private_data;
378 struct em28xx *dev = fh->dev; 417 struct em28xx *dev = fh->dev;
379 418
419
420 if (unlikely(res_get(fh) < 0))
421 return -EBUSY;
422
380 mutex_lock(&dev->lock); 423 mutex_lock(&dev->lock);
381 424
382 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 425 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
383 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); 426 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
384 427
385 if (dev->reader > 0 && fh->reader == 0) {
386 mutex_unlock(&dev->lock);
387 return -EBUSY;
388 }
389
390 if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 428 if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
391 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); 429 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
392 em28xx_videodbg("not supported yet! ...\n"); 430 em28xx_videodbg("not supported yet! ...\n");
@@ -425,9 +463,6 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
425 " the device again to choose the read method\n"); 463 " the device again to choose the read method\n");
426 mutex_unlock(&dev->lock); 464 mutex_unlock(&dev->lock);
427 return -EINVAL; 465 return -EINVAL;
428 } else {
429 dev->reader = 1;
430 fh->reader = 1;
431 } 466 }
432 467
433 if (dev->io == IO_NONE) { 468 if (dev->io == IO_NONE) {
@@ -499,6 +534,9 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
499 struct em28xx_fh *fh = filp->private_data; 534 struct em28xx_fh *fh = filp->private_data;
500 struct em28xx *dev = fh->dev; 535 struct em28xx *dev = fh->dev;
501 536
537 if (unlikely(res_get(fh) < 0))
538 return POLLERR;
539
502 mutex_lock(&dev->lock); 540 mutex_lock(&dev->lock);
503 541
504 if (dev->state & DEV_DISCONNECTED) { 542 if (dev->state & DEV_DISCONNECTED) {
@@ -572,15 +610,10 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
572 void *pos; 610 void *pos;
573 u32 i; 611 u32 i;
574 612
575 mutex_lock(&dev->lock); 613 if (unlikely(res_get(fh) < 0))
576
577 if (dev->reader > 0 && fh->reader == 0) {
578 mutex_unlock(&dev->lock);
579 return -EBUSY; 614 return -EBUSY;
580 } else { 615
581 dev->reader = 1; 616 mutex_lock(&dev->lock);
582 fh->reader = 1;
583 }
584 617
585 if (dev->state & DEV_DISCONNECTED) { 618 if (dev->state & DEV_DISCONNECTED) {
586 em28xx_videodbg("mmap: device not present\n"); 619 em28xx_videodbg("mmap: device not present\n");
@@ -1219,6 +1252,9 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1219 if (list_empty(&dev->inqueue)) 1252 if (list_empty(&dev->inqueue))
1220 return -EINVAL; 1253 return -EINVAL;
1221 1254
1255 if (unlikely(res_get(fh) < 0))
1256 return -EBUSY;
1257
1222 dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ 1258 dev->stream = STREAM_ON; /* FIXME: Start video capture here? */
1223 1259
1224 em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); 1260 em28xx_videodbg("VIDIOC_STREAMON: starting stream\n");
@@ -1243,7 +1279,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1243 } 1279 }
1244 } 1280 }
1245 1281
1246 fh->reader = 0;
1247 em28xx_empty_framequeues(dev); 1282 em28xx_empty_framequeues(dev);
1248 mutex_unlock(&dev->lock); 1283 mutex_unlock(&dev->lock);
1249 1284