diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/soc_camera.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b03ffecb7438..9758217470f0 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -507,9 +507,12 @@ static int soc_camera_open(struct file *file) | |||
507 | 507 | ||
508 | ici = to_soc_camera_host(icd->parent); | 508 | ici = to_soc_camera_host(icd->parent); |
509 | 509 | ||
510 | if (mutex_lock_interruptible(&icd->video_lock)) | ||
511 | return -ERESTARTSYS; | ||
510 | if (!try_module_get(ici->ops->owner)) { | 512 | if (!try_module_get(ici->ops->owner)) { |
511 | dev_err(icd->pdev, "Couldn't lock capture bus driver.\n"); | 513 | dev_err(icd->pdev, "Couldn't lock capture bus driver.\n"); |
512 | return -EINVAL; | 514 | ret = -EINVAL; |
515 | goto emodule; | ||
513 | } | 516 | } |
514 | 517 | ||
515 | icd->use_count++; | 518 | icd->use_count++; |
@@ -570,6 +573,7 @@ static int soc_camera_open(struct file *file) | |||
570 | } | 573 | } |
571 | v4l2_ctrl_handler_setup(&icd->ctrl_handler); | 574 | v4l2_ctrl_handler_setup(&icd->ctrl_handler); |
572 | } | 575 | } |
576 | mutex_unlock(&icd->video_lock); | ||
573 | 577 | ||
574 | file->private_data = icd; | 578 | file->private_data = icd; |
575 | dev_dbg(icd->pdev, "camera device open\n"); | 579 | dev_dbg(icd->pdev, "camera device open\n"); |
@@ -590,6 +594,8 @@ epower: | |||
590 | eiciadd: | 594 | eiciadd: |
591 | icd->use_count--; | 595 | icd->use_count--; |
592 | module_put(ici->ops->owner); | 596 | module_put(ici->ops->owner); |
597 | emodule: | ||
598 | mutex_unlock(&icd->video_lock); | ||
593 | 599 | ||
594 | return ret; | 600 | return ret; |
595 | } | 601 | } |
@@ -599,6 +605,7 @@ static int soc_camera_close(struct file *file) | |||
599 | struct soc_camera_device *icd = file->private_data; | 605 | struct soc_camera_device *icd = file->private_data; |
600 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 606 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
601 | 607 | ||
608 | mutex_lock(&icd->video_lock); | ||
602 | icd->use_count--; | 609 | icd->use_count--; |
603 | if (!icd->use_count) { | 610 | if (!icd->use_count) { |
604 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 611 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
@@ -615,6 +622,7 @@ static int soc_camera_close(struct file *file) | |||
615 | 622 | ||
616 | if (icd->streamer == file) | 623 | if (icd->streamer == file) |
617 | icd->streamer = NULL; | 624 | icd->streamer = NULL; |
625 | mutex_unlock(&icd->video_lock); | ||
618 | 626 | ||
619 | module_put(ici->ops->owner); | 627 | module_put(ici->ops->owner); |
620 | 628 | ||
@@ -645,10 +653,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) | |||
645 | if (icd->streamer != file) | 653 | if (icd->streamer != file) |
646 | return -EBUSY; | 654 | return -EBUSY; |
647 | 655 | ||
656 | if (mutex_lock_interruptible(&icd->video_lock)) | ||
657 | return -ERESTARTSYS; | ||
648 | if (ici->ops->init_videobuf) | 658 | if (ici->ops->init_videobuf) |
649 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); | 659 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); |
650 | else | 660 | else |
651 | err = vb2_mmap(&icd->vb2_vidq, vma); | 661 | err = vb2_mmap(&icd->vb2_vidq, vma); |
662 | mutex_unlock(&icd->video_lock); | ||
652 | 663 | ||
653 | dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n", | 664 | dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n", |
654 | (unsigned long)vma->vm_start, | 665 | (unsigned long)vma->vm_start, |
@@ -662,16 +673,18 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) | |||
662 | { | 673 | { |
663 | struct soc_camera_device *icd = file->private_data; | 674 | struct soc_camera_device *icd = file->private_data; |
664 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 675 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
676 | unsigned res = POLLERR; | ||
665 | 677 | ||
666 | if (icd->streamer != file) | 678 | if (icd->streamer != file) |
667 | return -EBUSY; | ||
668 | |||
669 | if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) { | ||
670 | dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); | ||
671 | return POLLERR; | 679 | return POLLERR; |
672 | } | ||
673 | 680 | ||
674 | return ici->ops->poll(file, pt); | 681 | mutex_lock(&icd->video_lock); |
682 | if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) | ||
683 | dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); | ||
684 | else | ||
685 | res = ici->ops->poll(file, pt); | ||
686 | mutex_unlock(&icd->video_lock); | ||
687 | return res; | ||
675 | } | 688 | } |
676 | 689 | ||
677 | void soc_camera_lock(struct vb2_queue *vq) | 690 | void soc_camera_lock(struct vb2_queue *vq) |
@@ -1432,10 +1445,6 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1432 | vdev->tvnorms = V4L2_STD_UNKNOWN; | 1445 | vdev->tvnorms = V4L2_STD_UNKNOWN; |
1433 | vdev->ctrl_handler = &icd->ctrl_handler; | 1446 | vdev->ctrl_handler = &icd->ctrl_handler; |
1434 | vdev->lock = &icd->video_lock; | 1447 | vdev->lock = &icd->video_lock; |
1435 | /* Locking in file operations other than ioctl should be done | ||
1436 | by the driver, not the V4L2 core. | ||
1437 | This driver needs auditing so that this flag can be removed. */ | ||
1438 | set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); | ||
1439 | 1448 | ||
1440 | icd->vdev = vdev; | 1449 | icd->vdev = vdev; |
1441 | 1450 | ||