aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorSascha Sommer <saschasommer@freenet.de>2007-11-03 20:22:38 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:01:55 -0500
commit5a80415bcabf2b59e8c34db6e743c54582cfd3c2 (patch)
tree0702641680d71fc50826cb98c3e330d35b993aa5 /drivers/media/video
parentea4fd5679b258d8ae85124a47b587a53ba6409de (diff)
V4L/DVB (6538): em28xx: fix locking to allow accesses from 2 different threads at the same time
The attached patch modifies the em28xx driver so that there can be ioctls from multiple different threads. This is necessary for capture apps like MPlayer that use different threads for capturing and channel tuning. Now the locking is only done for the ioctls that change properties of the device or access the i2c bus. It also removes some locks that look unnecessary: In em28xx_init_dev: the videodevice is not registered yet so nothing can access the hardware meanwhile, the device struct is not assigned to the interface yet so no race with disconnect is possible In em28xx_release_resources: it gets only called when dev->lock is already held Signed-off-by: Sascha Sommer <saschasommer@freenet.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c151
-rw-r--r--drivers/media/video/em28xx/em28xx.h2
2 files changed, 80 insertions, 73 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 18b8568c634c..bc495a11dc2d 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -126,8 +126,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
126 126
127static struct usb_driver em28xx_usb_driver; 127static struct usb_driver em28xx_usb_driver;
128 128
129static DEFINE_MUTEX(em28xx_sysfs_lock);
130static DECLARE_RWSEM(em28xx_disconnect);
131 129
132/********************* v4l2 interface ******************************************/ 130/********************* v4l2 interface ******************************************/
133 131
@@ -253,22 +251,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
253 em28xx_videodbg("open minor=%d type=%s users=%d\n", 251 em28xx_videodbg("open minor=%d type=%s users=%d\n",
254 minor,v4l2_type_names[dev->type],dev->users); 252 minor,v4l2_type_names[dev->type],dev->users);
255 253
256 if (!down_read_trylock(&em28xx_disconnect)) 254 mutex_lock(&dev->lock);
257 return -ERESTARTSYS;
258 255
259 if (dev->users) { 256 if (dev->users) {
260 em28xx_warn("this driver can be opened only once\n"); 257 em28xx_warn("this driver can be opened only once\n");
261 up_read(&em28xx_disconnect); 258 mutex_unlock(&dev->lock);
262 return -EBUSY; 259 return -EBUSY;
263 } 260 }
264 261
265 mutex_init(&dev->fileop_lock); /* to 1 == available */
266 spin_lock_init(&dev->queue_lock); 262 spin_lock_init(&dev->queue_lock);
267 init_waitqueue_head(&dev->wait_frame); 263 init_waitqueue_head(&dev->wait_frame);
268 init_waitqueue_head(&dev->wait_stream); 264 init_waitqueue_head(&dev->wait_stream);
269 265
270 mutex_lock(&dev->lock);
271
272 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 266 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
273 em28xx_set_alternate(dev); 267 em28xx_set_alternate(dev);
274 268
@@ -306,7 +300,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
306 300
307err: 301err:
308 mutex_unlock(&dev->lock); 302 mutex_unlock(&dev->lock);
309 up_read(&em28xx_disconnect);
310 return errCode; 303 return errCode;
311} 304}
312 305
@@ -317,7 +310,6 @@ err:
317*/ 310*/
318static void em28xx_release_resources(struct em28xx *dev) 311static void em28xx_release_resources(struct em28xx *dev)
319{ 312{
320 mutex_lock(&em28xx_sysfs_lock);
321 313
322 /*FIXME: I2C IR should be disconnected */ 314 /*FIXME: I2C IR should be disconnected */
323 315
@@ -329,7 +321,6 @@ static void em28xx_release_resources(struct em28xx *dev)
329 video_unregister_device(dev->vbi_dev); 321 video_unregister_device(dev->vbi_dev);
330 em28xx_i2c_unregister(dev); 322 em28xx_i2c_unregister(dev);
331 usb_put_dev(dev->udev); 323 usb_put_dev(dev->udev);
332 mutex_unlock(&em28xx_sysfs_lock);
333 324
334 325
335 /* Mark device as unused */ 326 /* Mark device as unused */
@@ -389,6 +380,8 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
389 int ret = 0; 380 int ret = 0;
390 struct em28xx *dev = filp->private_data; 381 struct em28xx *dev = filp->private_data;
391 382
383 mutex_lock(&dev->lock);
384
392 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 385 if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
393 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n"); 386 em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
394 } 387 }
@@ -396,47 +389,46 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
396 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n"); 389 em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
397 em28xx_videodbg("not supported yet! ...\n"); 390 em28xx_videodbg("not supported yet! ...\n");
398 if (copy_to_user(buf, "", 1)) { 391 if (copy_to_user(buf, "", 1)) {
399 mutex_unlock(&dev->fileop_lock); 392 mutex_unlock(&dev->lock);
400 return -EFAULT; 393 return -EFAULT;
401 } 394 }
395 mutex_unlock(&dev->lock);
402 return (1); 396 return (1);
403 } 397 }
404 if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { 398 if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
405 em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n"); 399 em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
406 em28xx_videodbg("not supported yet! ...\n"); 400 em28xx_videodbg("not supported yet! ...\n");
407 if (copy_to_user(buf, "", 1)) { 401 if (copy_to_user(buf, "", 1)) {
408 mutex_unlock(&dev->fileop_lock); 402 mutex_unlock(&dev->lock);
409 return -EFAULT; 403 return -EFAULT;
410 } 404 }
405 mutex_unlock(&dev->lock);
411 return (1); 406 return (1);
412 } 407 }
413 408
414 if (mutex_lock_interruptible(&dev->fileop_lock))
415 return -ERESTARTSYS;
416
417 if (dev->state & DEV_DISCONNECTED) { 409 if (dev->state & DEV_DISCONNECTED) {
418 em28xx_videodbg("device not present\n"); 410 em28xx_videodbg("device not present\n");
419 mutex_unlock(&dev->fileop_lock); 411 mutex_unlock(&dev->lock);
420 return -ENODEV; 412 return -ENODEV;
421 } 413 }
422 414
423 if (dev->state & DEV_MISCONFIGURED) { 415 if (dev->state & DEV_MISCONFIGURED) {
424 em28xx_videodbg("device misconfigured; close and open it again\n"); 416 em28xx_videodbg("device misconfigured; close and open it again\n");
425 mutex_unlock(&dev->fileop_lock); 417 mutex_unlock(&dev->lock);
426 return -EIO; 418 return -EIO;
427 } 419 }
428 420
429 if (dev->io == IO_MMAP) { 421 if (dev->io == IO_MMAP) {
430 em28xx_videodbg ("IO method is set to mmap; close and open" 422 em28xx_videodbg ("IO method is set to mmap; close and open"
431 " the device again to choose the read method\n"); 423 " the device again to choose the read method\n");
432 mutex_unlock(&dev->fileop_lock); 424 mutex_unlock(&dev->lock);
433 return -EINVAL; 425 return -EINVAL;
434 } 426 }
435 427
436 if (dev->io == IO_NONE) { 428 if (dev->io == IO_NONE) {
437 if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) { 429 if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
438 em28xx_errdev("read failed, not enough memory\n"); 430 em28xx_errdev("read failed, not enough memory\n");
439 mutex_unlock(&dev->fileop_lock); 431 mutex_unlock(&dev->lock);
440 return -ENOMEM; 432 return -ENOMEM;
441 } 433 }
442 dev->io = IO_READ; 434 dev->io = IO_READ;
@@ -445,13 +437,13 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
445 } 437 }
446 438
447 if (!count) { 439 if (!count) {
448 mutex_unlock(&dev->fileop_lock); 440 mutex_unlock(&dev->lock);
449 return 0; 441 return 0;
450 } 442 }
451 443
452 if (list_empty(&dev->outqueue)) { 444 if (list_empty(&dev->outqueue)) {
453 if (filp->f_flags & O_NONBLOCK) { 445 if (filp->f_flags & O_NONBLOCK) {
454 mutex_unlock(&dev->fileop_lock); 446 mutex_unlock(&dev->lock);
455 return -EAGAIN; 447 return -EAGAIN;
456 } 448 }
457 ret = wait_event_interruptible 449 ret = wait_event_interruptible
@@ -459,11 +451,11 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
459 (!list_empty(&dev->outqueue)) || 451 (!list_empty(&dev->outqueue)) ||
460 (dev->state & DEV_DISCONNECTED)); 452 (dev->state & DEV_DISCONNECTED));
461 if (ret) { 453 if (ret) {
462 mutex_unlock(&dev->fileop_lock); 454 mutex_unlock(&dev->lock);
463 return ret; 455 return ret;
464 } 456 }
465 if (dev->state & DEV_DISCONNECTED) { 457 if (dev->state & DEV_DISCONNECTED) {
466 mutex_unlock(&dev->fileop_lock); 458 mutex_unlock(&dev->lock);
467 return -ENODEV; 459 return -ENODEV;
468 } 460 }
469 } 461 }
@@ -482,12 +474,12 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
482 count = f->buf.length; 474 count = f->buf.length;
483 475
484 if (copy_to_user(buf, f->bufmem, count)) { 476 if (copy_to_user(buf, f->bufmem, count)) {
485 mutex_unlock(&dev->fileop_lock); 477 mutex_unlock(&dev->lock);
486 return -EFAULT; 478 return -EFAULT;
487 } 479 }
488 *f_pos += count; 480 *f_pos += count;
489 481
490 mutex_unlock(&dev->fileop_lock); 482 mutex_unlock(&dev->lock);
491 483
492 return count; 484 return count;
493} 485}
@@ -501,8 +493,7 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
501 unsigned int mask = 0; 493 unsigned int mask = 0;
502 struct em28xx *dev = filp->private_data; 494 struct em28xx *dev = filp->private_data;
503 495
504 if (mutex_lock_interruptible(&dev->fileop_lock)) 496 mutex_lock(&dev->lock);
505 return POLLERR;
506 497
507 if (dev->state & DEV_DISCONNECTED) { 498 if (dev->state & DEV_DISCONNECTED) {
508 em28xx_videodbg("device not present\n"); 499 em28xx_videodbg("device not present\n");
@@ -527,13 +518,13 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
527 if (!list_empty(&dev->outqueue)) 518 if (!list_empty(&dev->outqueue))
528 mask |= POLLIN | POLLRDNORM; 519 mask |= POLLIN | POLLRDNORM;
529 520
530 mutex_unlock(&dev->fileop_lock); 521 mutex_unlock(&dev->lock);
531 522
532 return mask; 523 return mask;
533 } 524 }
534 } 525 }
535 526
536 mutex_unlock(&dev->fileop_lock); 527 mutex_unlock(&dev->lock);
537 return POLLERR; 528 return POLLERR;
538} 529}
539 530
@@ -575,25 +566,24 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
575 566
576 struct em28xx *dev = filp->private_data; 567 struct em28xx *dev = filp->private_data;
577 568
578 if (mutex_lock_interruptible(&dev->fileop_lock)) 569 mutex_lock(&dev->lock);
579 return -ERESTARTSYS;
580 570
581 if (dev->state & DEV_DISCONNECTED) { 571 if (dev->state & DEV_DISCONNECTED) {
582 em28xx_videodbg("mmap: device not present\n"); 572 em28xx_videodbg("mmap: device not present\n");
583 mutex_unlock(&dev->fileop_lock); 573 mutex_unlock(&dev->lock);
584 return -ENODEV; 574 return -ENODEV;
585 } 575 }
586 576
587 if (dev->state & DEV_MISCONFIGURED) { 577 if (dev->state & DEV_MISCONFIGURED) {
588 em28xx_videodbg ("mmap: Device is misconfigured; close and " 578 em28xx_videodbg ("mmap: Device is misconfigured; close and "
589 "open it again\n"); 579 "open it again\n");
590 mutex_unlock(&dev->fileop_lock); 580 mutex_unlock(&dev->lock);
591 return -EIO; 581 return -EIO;
592 } 582 }
593 583
594 if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || 584 if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
595 size != PAGE_ALIGN(dev->frame[0].buf.length)) { 585 size != PAGE_ALIGN(dev->frame[0].buf.length)) {
596 mutex_unlock(&dev->fileop_lock); 586 mutex_unlock(&dev->lock);
597 return -EINVAL; 587 return -EINVAL;
598 } 588 }
599 589
@@ -603,7 +593,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
603 } 593 }
604 if (i == dev->num_frames) { 594 if (i == dev->num_frames) {
605 em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); 595 em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
606 mutex_unlock(&dev->fileop_lock); 596 mutex_unlock(&dev->lock);
607 return -EINVAL; 597 return -EINVAL;
608 } 598 }
609 599
@@ -615,7 +605,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
615 while (size > 0) { /* size is page-aligned */ 605 while (size > 0) { /* size is page-aligned */
616 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { 606 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
617 em28xx_videodbg("mmap: vm_insert_page failed\n"); 607 em28xx_videodbg("mmap: vm_insert_page failed\n");
618 mutex_unlock(&dev->fileop_lock); 608 mutex_unlock(&dev->lock);
619 return -EAGAIN; 609 return -EAGAIN;
620 } 610 }
621 start += PAGE_SIZE; 611 start += PAGE_SIZE;
@@ -627,7 +617,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
627 vma->vm_private_data = &dev->frame[i]; 617 vma->vm_private_data = &dev->frame[i];
628 618
629 em28xx_vm_open(vma); 619 em28xx_vm_open(vma);
630 mutex_unlock(&dev->fileop_lock); 620 mutex_unlock(&dev->lock);
631 return 0; 621 return 0;
632} 622}
633 623
@@ -1084,7 +1074,9 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1084 } 1074 }
1085 } 1075 }
1086 } 1076 }
1077 mutex_lock(&dev->lock);
1087 em28xx_i2c_call_clients(dev,cmd,qc); 1078 em28xx_i2c_call_clients(dev,cmd,qc);
1079 mutex_unlock(&dev->lock);
1088 if (qc->type) 1080 if (qc->type)
1089 return 0; 1081 return 0;
1090 else 1082 else
@@ -1098,7 +1090,9 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1098 if (!dev->has_msp34xx) 1090 if (!dev->has_msp34xx)
1099 retval=em28xx_get_ctrl(dev, ctrl); 1091 retval=em28xx_get_ctrl(dev, ctrl);
1100 if (retval==-EINVAL) { 1092 if (retval==-EINVAL) {
1093 mutex_lock(&dev->lock);
1101 em28xx_i2c_call_clients(dev,cmd,arg); 1094 em28xx_i2c_call_clients(dev,cmd,arg);
1095 mutex_unlock(&dev->lock);
1102 return 0; 1096 return 0;
1103 } else return retval; 1097 } else return retval;
1104 } 1098 }
@@ -1106,21 +1100,26 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1106 { 1100 {
1107 struct v4l2_control *ctrl = arg; 1101 struct v4l2_control *ctrl = arg;
1108 u8 i; 1102 u8 i;
1103 mutex_lock(&dev->lock);
1109 1104
1110 if (!dev->has_msp34xx){ 1105 if (!dev->has_msp34xx){
1111 for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { 1106 for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
1112 if (ctrl->id == em28xx_qctrl[i].id) { 1107 if (ctrl->id == em28xx_qctrl[i].id) {
1108 int retval=-EINVAL;
1113 if (ctrl->value < 1109 if (ctrl->value <
1114 em28xx_qctrl[i].minimum 1110 em28xx_qctrl[i].minimum
1115 || ctrl->value > 1111 || ctrl->value >
1116 em28xx_qctrl[i].maximum) 1112 em28xx_qctrl[i].maximum)
1117 return -ERANGE; 1113 return -ERANGE;
1118 return em28xx_set_ctrl(dev, ctrl); 1114 retval = em28xx_set_ctrl(dev, ctrl);
1115 mutex_unlock(&dev->lock);
1116 return retval;
1119 } 1117 }
1120 } 1118 }
1121 } 1119 }
1122 1120
1123 em28xx_i2c_call_clients(dev,cmd,arg); 1121 em28xx_i2c_call_clients(dev,cmd,arg);
1122 mutex_unlock(&dev->lock);
1124 return 0; 1123 return 0;
1125 } 1124 }
1126 /* --- tuner ioctls ------------------------------------------ */ 1125 /* --- tuner ioctls ------------------------------------------ */
@@ -1220,12 +1219,16 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
1220 || dev->io != IO_MMAP) 1219 || dev->io != IO_MMAP)
1221 return -EINVAL; 1220 return -EINVAL;
1222 1221
1222 mutex_lock(&dev->lock);
1223 if (dev->stream == STREAM_ON) { 1223 if (dev->stream == STREAM_ON) {
1224 em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); 1224 em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n");
1225 if ((ret = em28xx_stream_interrupt(dev))) 1225 if ((ret = em28xx_stream_interrupt(dev))){
1226 mutex_unlock(&dev->lock);
1226 return ret; 1227 return ret;
1228 }
1227 } 1229 }
1228 em28xx_empty_framequeues(dev); 1230 em28xx_empty_framequeues(dev);
1231 mutex_unlock(&dev->lock);
1229 1232
1230 return 0; 1233 return 0;
1231 } 1234 }
@@ -1291,11 +1294,23 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
1291 return 0; 1294 return 0;
1292 } 1295 }
1293 case VIDIOC_G_FMT: 1296 case VIDIOC_G_FMT:
1294 return em28xx_get_fmt(dev, (struct v4l2_format *) arg); 1297 {
1298 int retval;
1299 mutex_lock(&dev->lock);
1300 retval = em28xx_get_fmt(dev, (struct v4l2_format *) arg);
1301 mutex_unlock(&dev->lock);
1302 return retval;
1295 1303
1304 }
1296 case VIDIOC_TRY_FMT: 1305 case VIDIOC_TRY_FMT:
1297 case VIDIOC_S_FMT: 1306 case VIDIOC_S_FMT:
1298 return em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg); 1307 {
1308 int retval;
1309 mutex_lock(&dev->lock);
1310 retval = em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg);
1311 mutex_unlock(&dev->lock);
1312 return retval;
1313 }
1299 1314
1300 case VIDIOC_REQBUFS: 1315 case VIDIOC_REQBUFS:
1301 { 1316 {
@@ -1320,10 +1335,13 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
1320 return -EINVAL; 1335 return -EINVAL;
1321 } 1336 }
1322 1337
1338 mutex_lock(&dev->lock);
1323 if (dev->stream == STREAM_ON) { 1339 if (dev->stream == STREAM_ON) {
1324 em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); 1340 em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
1325 if ((ret = em28xx_stream_interrupt(dev))) 1341 if ((ret = em28xx_stream_interrupt(dev))){
1342 mutex_unlock(&dev->lock);
1326 return ret; 1343 return ret;
1344 }
1327 } 1345 }
1328 1346
1329 em28xx_empty_framequeues(dev); 1347 em28xx_empty_framequeues(dev);
@@ -1338,6 +1356,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
1338 em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", 1356 em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n",
1339 rb->count); 1357 rb->count);
1340 dev->io = rb->count ? IO_MMAP : IO_NONE; 1358 dev->io = rb->count ? IO_MMAP : IO_NONE;
1359 mutex_unlock(&dev->lock);
1341 return 0; 1360 return 0;
1342 } 1361 }
1343 case VIDIOC_QUERYBUF: 1362 case VIDIOC_QUERYBUF:
@@ -1439,26 +1458,19 @@ static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp,
1439 int ret = 0; 1458 int ret = 0;
1440 struct em28xx *dev = filp->private_data; 1459 struct em28xx *dev = filp->private_data;
1441 1460
1442 if (mutex_lock_interruptible(&dev->fileop_lock))
1443 return -ERESTARTSYS;
1444
1445 if (dev->state & DEV_DISCONNECTED) { 1461 if (dev->state & DEV_DISCONNECTED) {
1446 em28xx_errdev("v4l2 ioctl: device not present\n"); 1462 em28xx_errdev("v4l2 ioctl: device not present\n");
1447 mutex_unlock(&dev->fileop_lock);
1448 return -ENODEV; 1463 return -ENODEV;
1449 } 1464 }
1450 1465
1451 if (dev->state & DEV_MISCONFIGURED) { 1466 if (dev->state & DEV_MISCONFIGURED) {
1452 em28xx_errdev 1467 em28xx_errdev
1453 ("v4l2 ioctl: device is misconfigured; close and open it again\n"); 1468 ("v4l2 ioctl: device is misconfigured; close and open it again\n");
1454 mutex_unlock(&dev->fileop_lock);
1455 return -EIO; 1469 return -EIO;
1456 } 1470 }
1457 1471
1458 ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl); 1472 ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl);
1459 1473
1460 mutex_unlock(&dev->fileop_lock);
1461
1462 return ret; 1474 return ret;
1463} 1475}
1464 1476
@@ -1519,8 +1531,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1519 return -ENOMEM; 1531 return -ENOMEM;
1520 } 1532 }
1521 1533
1522 mutex_lock(&dev->lock);
1523
1524 /* register i2c bus */ 1534 /* register i2c bus */
1525 em28xx_i2c_register(dev); 1535 em28xx_i2c_register(dev);
1526 1536
@@ -1530,8 +1540,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1530 /* configure the device */ 1540 /* configure the device */
1531 em28xx_config_i2c(dev); 1541 em28xx_config_i2c(dev);
1532 1542
1533 mutex_unlock(&dev->lock);
1534
1535 for (i = 0; i < TVNORMS; i++) 1543 for (i = 0; i < TVNORMS; i++)
1536 if (em28xx_boards[dev->model].norm == tvnorms[i].mode) 1544 if (em28xx_boards[dev->model].norm == tvnorms[i].mode)
1537 break; 1545 break;
@@ -1599,8 +1607,18 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1599 1607
1600 list_add_tail(&dev->devlist,&em28xx_devlist); 1608 list_add_tail(&dev->devlist,&em28xx_devlist);
1601 1609
1610
1611 if (dev->has_msp34xx) {
1612 /* Send a reset to other chips via gpio */
1613 em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
1614 msleep(3);
1615 em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
1616 msleep(3);
1617
1618 }
1619 video_mux(dev, 0);
1620
1602 /* register v4l2 device */ 1621 /* register v4l2 device */
1603 mutex_lock(&dev->lock);
1604 if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, 1622 if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
1605 video_nr[dev->devno]))) { 1623 video_nr[dev->devno]))) {
1606 em28xx_errdev("unable to register video device (error=%i).\n", 1624 em28xx_errdev("unable to register video device (error=%i).\n",
@@ -1627,18 +1645,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1627 printk("registered VBI\n"); 1645 printk("registered VBI\n");
1628 } 1646 }
1629 1647
1630 if (dev->has_msp34xx) {
1631 /* Send a reset to other chips via gpio */
1632 em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
1633 msleep(3);
1634 em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
1635 msleep(3);
1636
1637 }
1638 video_mux(dev, 0);
1639
1640 mutex_unlock(&dev->lock);
1641
1642 em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", 1648 em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
1643 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, 1649 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
1644 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); 1650 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
@@ -1762,18 +1768,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
1762 */ 1768 */
1763static void em28xx_usb_disconnect(struct usb_interface *interface) 1769static void em28xx_usb_disconnect(struct usb_interface *interface)
1764{ 1770{
1765 struct em28xx *dev = usb_get_intfdata(interface); 1771 struct em28xx *dev;
1772
1773 dev = usb_get_intfdata(interface);
1766 usb_set_intfdata(interface, NULL); 1774 usb_set_intfdata(interface, NULL);
1767 1775
1768 if (!dev) 1776 if (!dev)
1769 return; 1777 return;
1770 1778
1771 down_write(&em28xx_disconnect); 1779 em28xx_info("disconnecting %s\n", dev->vdev->name);
1772 1780
1781 /* wait until all current v4l2 io is finished then deallocate resources */
1773 mutex_lock(&dev->lock); 1782 mutex_lock(&dev->lock);
1774 1783
1775 em28xx_info("disconnecting %s\n", dev->vdev->name);
1776
1777 wake_up_interruptible_all(&dev->open); 1784 wake_up_interruptible_all(&dev->open);
1778 1785
1779 if (dev->users) { 1786 if (dev->users) {
@@ -1792,6 +1799,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
1792 em28xx_release_resources(dev); 1799 em28xx_release_resources(dev);
1793 } 1800 }
1794 1801
1802
1795 mutex_unlock(&dev->lock); 1803 mutex_unlock(&dev->lock);
1796 1804
1797 if (!dev->users) { 1805 if (!dev->users) {
@@ -1799,7 +1807,6 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
1799 kfree(dev); 1807 kfree(dev);
1800 } 1808 }
1801 1809
1802 up_write(&em28xx_disconnect);
1803} 1810}
1804 1811
1805static struct usb_driver em28xx_usb_driver = { 1812static struct usb_driver em28xx_usb_driver = {
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 209f6f9d5581..65670ae2945b 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -265,7 +265,7 @@ struct em28xx {
265 enum em28xx_stream_state stream; 265 enum em28xx_stream_state stream;
266 enum em28xx_io_method io; 266 enum em28xx_io_method io;
267 /* locks */ 267 /* locks */
268 struct mutex lock, fileop_lock; 268 struct mutex lock;
269 spinlock_t queue_lock; 269 spinlock_t queue_lock;
270 struct list_head inqueue, outqueue; 270 struct list_head inqueue, outqueue;
271 wait_queue_head_t open, wait_frame, wait_stream; 271 wait_queue_head_t open, wait_frame, wait_stream;