diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-06-27 08:56:17 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 18:22:44 -0400 |
commit | c2d430af08f38a0b3145c3b60381146b8ac88c88 (patch) | |
tree | a63e00cf263b47d7c9e8648cc5af27d8c74b0184 | |
parent | 837c7e4256d5285700fe0d500eeb15801b55bb0e (diff) |
[media] s5p-fimc: Remove V4L2_FL_LOCK_ALL_FOPS flag
This patch adds locking for open(), close(), poll() and mmap()
file operations in the driver as a follow up to the changes
done in commit 5126f2590bee412e3053de851cb07f531
"v4l2-dev: add flag to have the core lock all file operations".
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 78 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-m2m.c | 45 |
2 files changed, 87 insertions, 36 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 6a34183564d2..8e413dd3c0b0 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -480,48 +480,59 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc); | |||
480 | static int fimc_capture_open(struct file *file) | 480 | static int fimc_capture_open(struct file *file) |
481 | { | 481 | { |
482 | struct fimc_dev *fimc = video_drvdata(file); | 482 | struct fimc_dev *fimc = video_drvdata(file); |
483 | int ret; | 483 | int ret = -EBUSY; |
484 | 484 | ||
485 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); | 485 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); |
486 | 486 | ||
487 | if (mutex_lock_interruptible(&fimc->lock)) | ||
488 | return -ERESTARTSYS; | ||
489 | |||
487 | if (fimc_m2m_active(fimc)) | 490 | if (fimc_m2m_active(fimc)) |
488 | return -EBUSY; | 491 | goto unlock; |
489 | 492 | ||
490 | set_bit(ST_CAPT_BUSY, &fimc->state); | 493 | set_bit(ST_CAPT_BUSY, &fimc->state); |
491 | ret = pm_runtime_get_sync(&fimc->pdev->dev); | 494 | ret = pm_runtime_get_sync(&fimc->pdev->dev); |
492 | if (ret < 0) | 495 | if (ret < 0) |
493 | return ret; | 496 | goto unlock; |
494 | 497 | ||
495 | ret = v4l2_fh_open(file); | 498 | ret = v4l2_fh_open(file); |
496 | if (ret) | 499 | if (ret) { |
497 | return ret; | 500 | pm_runtime_put(&fimc->pdev->dev); |
498 | 501 | goto unlock; | |
499 | if (++fimc->vid_cap.refcnt != 1) | 502 | } |
500 | return 0; | ||
501 | 503 | ||
502 | ret = fimc_pipeline_initialize(&fimc->pipeline, | 504 | if (++fimc->vid_cap.refcnt == 1) { |
505 | ret = fimc_pipeline_initialize(&fimc->pipeline, | ||
503 | &fimc->vid_cap.vfd->entity, true); | 506 | &fimc->vid_cap.vfd->entity, true); |
504 | if (ret < 0) { | ||
505 | clear_bit(ST_CAPT_BUSY, &fimc->state); | ||
506 | pm_runtime_put_sync(&fimc->pdev->dev); | ||
507 | fimc->vid_cap.refcnt--; | ||
508 | v4l2_fh_release(file); | ||
509 | return ret; | ||
510 | } | ||
511 | ret = fimc_capture_ctrls_create(fimc); | ||
512 | 507 | ||
513 | if (!ret && !fimc->vid_cap.user_subdev_api) | 508 | if (!ret && !fimc->vid_cap.user_subdev_api) |
514 | ret = fimc_capture_set_default_format(fimc); | 509 | ret = fimc_capture_set_default_format(fimc); |
510 | |||
511 | if (!ret) | ||
512 | ret = fimc_capture_ctrls_create(fimc); | ||
515 | 513 | ||
514 | if (ret < 0) { | ||
515 | clear_bit(ST_CAPT_BUSY, &fimc->state); | ||
516 | pm_runtime_put_sync(&fimc->pdev->dev); | ||
517 | fimc->vid_cap.refcnt--; | ||
518 | v4l2_fh_release(file); | ||
519 | } | ||
520 | } | ||
521 | unlock: | ||
522 | mutex_unlock(&fimc->lock); | ||
516 | return ret; | 523 | return ret; |
517 | } | 524 | } |
518 | 525 | ||
519 | static int fimc_capture_close(struct file *file) | 526 | static int fimc_capture_close(struct file *file) |
520 | { | 527 | { |
521 | struct fimc_dev *fimc = video_drvdata(file); | 528 | struct fimc_dev *fimc = video_drvdata(file); |
529 | int ret; | ||
522 | 530 | ||
523 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); | 531 | dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); |
524 | 532 | ||
533 | if (mutex_lock_interruptible(&fimc->lock)) | ||
534 | return -ERESTARTSYS; | ||
535 | |||
525 | if (--fimc->vid_cap.refcnt == 0) { | 536 | if (--fimc->vid_cap.refcnt == 0) { |
526 | clear_bit(ST_CAPT_BUSY, &fimc->state); | 537 | clear_bit(ST_CAPT_BUSY, &fimc->state); |
527 | fimc_stop_capture(fimc, false); | 538 | fimc_stop_capture(fimc, false); |
@@ -535,22 +546,40 @@ static int fimc_capture_close(struct file *file) | |||
535 | vb2_queue_release(&fimc->vid_cap.vbq); | 546 | vb2_queue_release(&fimc->vid_cap.vbq); |
536 | fimc_ctrls_delete(fimc->vid_cap.ctx); | 547 | fimc_ctrls_delete(fimc->vid_cap.ctx); |
537 | } | 548 | } |
538 | return v4l2_fh_release(file); | 549 | |
550 | ret = v4l2_fh_release(file); | ||
551 | |||
552 | mutex_unlock(&fimc->lock); | ||
553 | return ret; | ||
539 | } | 554 | } |
540 | 555 | ||
541 | static unsigned int fimc_capture_poll(struct file *file, | 556 | static unsigned int fimc_capture_poll(struct file *file, |
542 | struct poll_table_struct *wait) | 557 | struct poll_table_struct *wait) |
543 | { | 558 | { |
544 | struct fimc_dev *fimc = video_drvdata(file); | 559 | struct fimc_dev *fimc = video_drvdata(file); |
560 | int ret; | ||
545 | 561 | ||
546 | return vb2_poll(&fimc->vid_cap.vbq, file, wait); | 562 | if (mutex_lock_interruptible(&fimc->lock)) |
563 | return POLL_ERR; | ||
564 | |||
565 | ret = vb2_poll(&fimc->vid_cap.vbq, file, wait); | ||
566 | mutex_unlock(&fimc->lock); | ||
567 | |||
568 | return ret; | ||
547 | } | 569 | } |
548 | 570 | ||
549 | static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) | 571 | static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma) |
550 | { | 572 | { |
551 | struct fimc_dev *fimc = video_drvdata(file); | 573 | struct fimc_dev *fimc = video_drvdata(file); |
574 | int ret; | ||
575 | |||
576 | if (mutex_lock_interruptible(&fimc->lock)) | ||
577 | return -ERESTARTSYS; | ||
552 | 578 | ||
553 | return vb2_mmap(&fimc->vid_cap.vbq, vma); | 579 | ret = vb2_mmap(&fimc->vid_cap.vbq, vma); |
580 | mutex_unlock(&fimc->lock); | ||
581 | |||
582 | return ret; | ||
554 | } | 583 | } |
555 | 584 | ||
556 | static const struct v4l2_file_operations fimc_capture_fops = { | 585 | static const struct v4l2_file_operations fimc_capture_fops = { |
@@ -1589,10 +1618,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, | |||
1589 | vfd->minor = -1; | 1618 | vfd->minor = -1; |
1590 | vfd->release = video_device_release; | 1619 | vfd->release = video_device_release; |
1591 | vfd->lock = &fimc->lock; | 1620 | vfd->lock = &fimc->lock; |
1592 | /* Locking in file operations other than ioctl should be done | 1621 | |
1593 | by the driver, not the V4L2 core. | ||
1594 | This driver needs auditing so that this flag can be removed. */ | ||
1595 | set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); | ||
1596 | video_set_drvdata(vfd, fimc); | 1622 | video_set_drvdata(vfd, fimc); |
1597 | 1623 | ||
1598 | vid_cap = &fimc->vid_cap; | 1624 | vid_cap = &fimc->vid_cap; |
diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/video/s5p-fimc/fimc-m2m.c index 4c58e0570962..41eda2e27488 100644 --- a/drivers/media/video/s5p-fimc/fimc-m2m.c +++ b/drivers/media/video/s5p-fimc/fimc-m2m.c | |||
@@ -642,21 +642,25 @@ static int fimc_m2m_open(struct file *file) | |||
642 | { | 642 | { |
643 | struct fimc_dev *fimc = video_drvdata(file); | 643 | struct fimc_dev *fimc = video_drvdata(file); |
644 | struct fimc_ctx *ctx; | 644 | struct fimc_ctx *ctx; |
645 | int ret; | 645 | int ret = -EBUSY; |
646 | 646 | ||
647 | dbg("pid: %d, state: 0x%lx, refcnt: %d", | 647 | dbg("pid: %d, state: 0x%lx, refcnt: %d", |
648 | task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); | 648 | task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); |
649 | 649 | ||
650 | if (mutex_lock_interruptible(&fimc->lock)) | ||
651 | return -ERESTARTSYS; | ||
650 | /* | 652 | /* |
651 | * Return if the corresponding video capture node | 653 | * Return if the corresponding video capture node |
652 | * is already opened. | 654 | * is already opened. |
653 | */ | 655 | */ |
654 | if (fimc->vid_cap.refcnt > 0) | 656 | if (fimc->vid_cap.refcnt > 0) |
655 | return -EBUSY; | 657 | goto unlock; |
656 | 658 | ||
657 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 659 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); |
658 | if (!ctx) | 660 | if (!ctx) { |
659 | return -ENOMEM; | 661 | ret = -ENOMEM; |
662 | goto unlock; | ||
663 | } | ||
660 | v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); | 664 | v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); |
661 | ctx->fimc_dev = fimc; | 665 | ctx->fimc_dev = fimc; |
662 | 666 | ||
@@ -687,6 +691,8 @@ static int fimc_m2m_open(struct file *file) | |||
687 | 691 | ||
688 | if (fimc->m2m.refcnt++ == 0) | 692 | if (fimc->m2m.refcnt++ == 0) |
689 | set_bit(ST_M2M_RUN, &fimc->state); | 693 | set_bit(ST_M2M_RUN, &fimc->state); |
694 | |||
695 | mutex_unlock(&fimc->lock); | ||
690 | return 0; | 696 | return 0; |
691 | 697 | ||
692 | error_c: | 698 | error_c: |
@@ -695,6 +701,8 @@ error_fh: | |||
695 | v4l2_fh_del(&ctx->fh); | 701 | v4l2_fh_del(&ctx->fh); |
696 | v4l2_fh_exit(&ctx->fh); | 702 | v4l2_fh_exit(&ctx->fh); |
697 | kfree(ctx); | 703 | kfree(ctx); |
704 | unlock: | ||
705 | mutex_unlock(&fimc->lock); | ||
698 | return ret; | 706 | return ret; |
699 | } | 707 | } |
700 | 708 | ||
@@ -706,6 +714,9 @@ static int fimc_m2m_release(struct file *file) | |||
706 | dbg("pid: %d, state: 0x%lx, refcnt= %d", | 714 | dbg("pid: %d, state: 0x%lx, refcnt= %d", |
707 | task_pid_nr(current), fimc->state, fimc->m2m.refcnt); | 715 | task_pid_nr(current), fimc->state, fimc->m2m.refcnt); |
708 | 716 | ||
717 | if (mutex_lock_interruptible(&fimc->lock)) | ||
718 | return -ERESTARTSYS; | ||
719 | |||
709 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 720 | v4l2_m2m_ctx_release(ctx->m2m_ctx); |
710 | fimc_ctrls_delete(ctx); | 721 | fimc_ctrls_delete(ctx); |
711 | v4l2_fh_del(&ctx->fh); | 722 | v4l2_fh_del(&ctx->fh); |
@@ -714,6 +725,8 @@ static int fimc_m2m_release(struct file *file) | |||
714 | if (--fimc->m2m.refcnt <= 0) | 725 | if (--fimc->m2m.refcnt <= 0) |
715 | clear_bit(ST_M2M_RUN, &fimc->state); | 726 | clear_bit(ST_M2M_RUN, &fimc->state); |
716 | kfree(ctx); | 727 | kfree(ctx); |
728 | |||
729 | mutex_unlock(&fimc->lock); | ||
717 | return 0; | 730 | return 0; |
718 | } | 731 | } |
719 | 732 | ||
@@ -721,16 +734,32 @@ static unsigned int fimc_m2m_poll(struct file *file, | |||
721 | struct poll_table_struct *wait) | 734 | struct poll_table_struct *wait) |
722 | { | 735 | { |
723 | struct fimc_ctx *ctx = fh_to_ctx(file->private_data); | 736 | struct fimc_ctx *ctx = fh_to_ctx(file->private_data); |
737 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
738 | int ret; | ||
724 | 739 | ||
725 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | 740 | if (mutex_lock_interruptible(&fimc->lock)) |
741 | return -ERESTARTSYS; | ||
742 | |||
743 | ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
744 | mutex_unlock(&fimc->lock); | ||
745 | |||
746 | return ret; | ||
726 | } | 747 | } |
727 | 748 | ||
728 | 749 | ||
729 | static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) | 750 | static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) |
730 | { | 751 | { |
731 | struct fimc_ctx *ctx = fh_to_ctx(file->private_data); | 752 | struct fimc_ctx *ctx = fh_to_ctx(file->private_data); |
753 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
754 | int ret; | ||
755 | |||
756 | if (mutex_lock_interruptible(&fimc->lock)) | ||
757 | return -ERESTARTSYS; | ||
732 | 758 | ||
733 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | 759 | ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); |
760 | mutex_unlock(&fimc->lock); | ||
761 | |||
762 | return ret; | ||
734 | } | 763 | } |
735 | 764 | ||
736 | static const struct v4l2_file_operations fimc_m2m_fops = { | 765 | static const struct v4l2_file_operations fimc_m2m_fops = { |
@@ -772,10 +801,6 @@ int fimc_register_m2m_device(struct fimc_dev *fimc, | |||
772 | vfd->minor = -1; | 801 | vfd->minor = -1; |
773 | vfd->release = video_device_release; | 802 | vfd->release = video_device_release; |
774 | vfd->lock = &fimc->lock; | 803 | vfd->lock = &fimc->lock; |
775 | /* Locking in file operations other than ioctl should be done | ||
776 | by the driver, not the V4L2 core. | ||
777 | This driver needs auditing so that this flag can be removed. */ | ||
778 | set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); | ||
779 | 804 | ||
780 | snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); | 805 | snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); |
781 | video_set_drvdata(vfd, fimc); | 806 | video_set_drvdata(vfd, fimc); |