diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-08-19 06:10:55 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-10-09 21:05:43 -0400 |
commit | baa4072d84e7a2e9954121c826d7bb8f1fb66b38 (patch) | |
tree | 0b354b98963f39c3089e9c5729d40b1d3a0d231c | |
parent | 1aa32c2ffd146dddd76babf842e998502f1b993a (diff) |
V4L/DVB (6056): ivtv: move serialization to the fileops level
Serialization is now done on the open/close/ioctl level and also when the
read/write/poll start an encoder/decoder stream.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 95 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 26 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 11 |
3 files changed, 76 insertions, 56 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 846e9bfa41f0..1f3c8d0310f5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -502,7 +502,9 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ | |||
502 | 502 | ||
503 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); | 503 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); |
504 | 504 | ||
505 | mutex_lock(&itv->serialize_lock); | ||
505 | rc = ivtv_start_capture(id); | 506 | rc = ivtv_start_capture(id); |
507 | mutex_unlock(&itv->serialize_lock); | ||
506 | if (rc) | 508 | if (rc) |
507 | return rc; | 509 | return rc; |
508 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | 510 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); |
@@ -613,7 +615,9 @@ retry: | |||
613 | } | 615 | } |
614 | 616 | ||
615 | /* Start decoder (returns 0 if already started) */ | 617 | /* Start decoder (returns 0 if already started) */ |
618 | mutex_lock(&itv->serialize_lock); | ||
616 | rc = ivtv_start_decoding(id, itv->speed); | 619 | rc = ivtv_start_decoding(id, itv->speed); |
620 | mutex_unlock(&itv->serialize_lock); | ||
617 | if (rc) { | 621 | if (rc) { |
618 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); | 622 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); |
619 | 623 | ||
@@ -681,8 +685,11 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | |||
681 | 685 | ||
682 | /* Start a capture if there is none */ | 686 | /* Start a capture if there is none */ |
683 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 687 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
684 | int rc = ivtv_start_capture(id); | 688 | int rc; |
685 | 689 | ||
690 | mutex_lock(&itv->serialize_lock); | ||
691 | rc = ivtv_start_capture(id); | ||
692 | mutex_unlock(&itv->serialize_lock); | ||
686 | if (rc) { | 693 | if (rc) { |
687 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", | 694 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", |
688 | s->name, rc); | 695 | s->name, rc); |
@@ -788,6 +795,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
788 | /* 'Unclaim' this stream */ | 795 | /* 'Unclaim' this stream */ |
789 | 796 | ||
790 | /* Stop radio */ | 797 | /* Stop radio */ |
798 | mutex_lock(&itv->serialize_lock); | ||
791 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { | 799 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { |
792 | /* Closing radio device, return to TV mode */ | 800 | /* Closing radio device, return to TV mode */ |
793 | ivtv_mute(itv); | 801 | ivtv_mute(itv); |
@@ -822,53 +830,26 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
822 | ivtv_stop_capture(id, 0); | 830 | ivtv_stop_capture(id, 0); |
823 | } | 831 | } |
824 | kfree(id); | 832 | kfree(id); |
833 | mutex_unlock(&itv->serialize_lock); | ||
825 | return 0; | 834 | return 0; |
826 | } | 835 | } |
827 | 836 | ||
828 | int ivtv_v4l2_open(struct inode *inode, struct file *filp) | 837 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) |
829 | { | 838 | { |
830 | int x, y = 0; | 839 | struct ivtv *itv = s->itv; |
831 | struct ivtv_open_id *item; | 840 | struct ivtv_open_id *item; |
832 | struct ivtv *itv = NULL; | ||
833 | struct ivtv_stream *s = NULL; | ||
834 | int minor = iminor(inode); | ||
835 | 841 | ||
836 | /* Find which card this open was on */ | ||
837 | spin_lock(&ivtv_cards_lock); | ||
838 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | ||
839 | /* find out which stream this open was on */ | ||
840 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | ||
841 | s = &ivtv_cards[x]->streams[y]; | ||
842 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | ||
843 | itv = ivtv_cards[x]; | ||
844 | break; | ||
845 | } | ||
846 | } | ||
847 | } | ||
848 | spin_unlock(&ivtv_cards_lock); | ||
849 | |||
850 | if (itv == NULL) { | ||
851 | /* Couldn't find a device registered | ||
852 | on that minor, shouldn't happen! */ | ||
853 | IVTV_WARN("No ivtv device found on minor %d\n", minor); | ||
854 | return -ENXIO; | ||
855 | } | ||
856 | |||
857 | if (ivtv_init_on_first_open(itv)) { | ||
858 | IVTV_ERR("Failed to initialize on minor %d\n", minor); | ||
859 | return -ENXIO; | ||
860 | } | ||
861 | IVTV_DEBUG_FILE("open %s\n", s->name); | 842 | IVTV_DEBUG_FILE("open %s\n", s->name); |
862 | 843 | ||
863 | if (y == IVTV_DEC_STREAM_TYPE_MPG && | 844 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG && |
864 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) | 845 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) |
865 | return -EBUSY; | 846 | return -EBUSY; |
866 | 847 | ||
867 | if (y == IVTV_DEC_STREAM_TYPE_YUV && | 848 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && |
868 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) | 849 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) |
869 | return -EBUSY; | 850 | return -EBUSY; |
870 | 851 | ||
871 | if (y == IVTV_DEC_STREAM_TYPE_YUV) { | 852 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { |
872 | if (read_reg(0x82c) == 0) { | 853 | if (read_reg(0x82c) == 0) { |
873 | IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); | 854 | IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); |
874 | /* return -ENODEV; */ | 855 | /* return -ENODEV; */ |
@@ -883,7 +864,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
883 | return -ENOMEM; | 864 | return -ENOMEM; |
884 | } | 865 | } |
885 | item->itv = itv; | 866 | item->itv = itv; |
886 | item->type = y; | 867 | item->type = s->type; |
887 | v4l2_prio_open(&itv->prio, &item->prio); | 868 | v4l2_prio_open(&itv->prio, &item->prio); |
888 | 869 | ||
889 | item->open_id = itv->open_id++; | 870 | item->open_id = itv->open_id++; |
@@ -925,14 +906,50 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
925 | } | 906 | } |
926 | 907 | ||
927 | /* YUV or MPG Decoding Mode? */ | 908 | /* YUV or MPG Decoding Mode? */ |
928 | if (y == IVTV_DEC_STREAM_TYPE_MPG) | 909 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) |
929 | clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | 910 | clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); |
930 | else if (y == IVTV_DEC_STREAM_TYPE_YUV) | 911 | else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) |
931 | { | ||
932 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | 912 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); |
913 | return 0; | ||
914 | } | ||
915 | |||
916 | int ivtv_v4l2_open(struct inode *inode, struct file *filp) | ||
917 | { | ||
918 | int res, x, y = 0; | ||
919 | struct ivtv *itv = NULL; | ||
920 | struct ivtv_stream *s = NULL; | ||
921 | int minor = iminor(inode); | ||
922 | |||
923 | /* Find which card this open was on */ | ||
924 | spin_lock(&ivtv_cards_lock); | ||
925 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | ||
926 | /* find out which stream this open was on */ | ||
927 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | ||
928 | s = &ivtv_cards[x]->streams[y]; | ||
929 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | ||
930 | itv = ivtv_cards[x]; | ||
931 | break; | ||
932 | } | ||
933 | } | ||
933 | } | 934 | } |
935 | spin_unlock(&ivtv_cards_lock); | ||
934 | 936 | ||
935 | return 0; | 937 | if (itv == NULL) { |
938 | /* Couldn't find a device registered | ||
939 | on that minor, shouldn't happen! */ | ||
940 | IVTV_WARN("No ivtv device found on minor %d\n", minor); | ||
941 | return -ENXIO; | ||
942 | } | ||
943 | |||
944 | mutex_lock(&itv->serialize_lock); | ||
945 | if (ivtv_init_on_first_open(itv)) { | ||
946 | IVTV_ERR("Failed to initialize on minor %d\n", minor); | ||
947 | mutex_unlock(&itv->serialize_lock); | ||
948 | return -ENXIO; | ||
949 | } | ||
950 | res = ivtv_serialized_open(s, filp); | ||
951 | mutex_unlock(&itv->serialize_lock); | ||
952 | return res; | ||
936 | } | 953 | } |
937 | 954 | ||
938 | void ivtv_mute(struct ivtv *itv) | 955 | void ivtv_mute(struct ivtv *itv) |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 2c0f27241332..2061d82653fc 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -1446,11 +1446,15 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1446 | return 0; | 1446 | return 0; |
1447 | if (nonblocking) | 1447 | if (nonblocking) |
1448 | return -EAGAIN; | 1448 | return -EAGAIN; |
1449 | /* wait for event */ | 1449 | /* Wait for event. Note that serialize_lock is locked, |
1450 | so to allow other processes to access the driver while | ||
1451 | we are waiting unlock first and later lock again. */ | ||
1452 | mutex_unlock(&itv->serialize_lock); | ||
1450 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); | 1453 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); |
1451 | if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) | 1454 | if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) |
1452 | schedule(); | 1455 | schedule(); |
1453 | finish_wait(&itv->event_waitq, &wait); | 1456 | finish_wait(&itv->event_waitq, &wait); |
1457 | mutex_lock(&itv->serialize_lock); | ||
1454 | if (signal_pending(current)) { | 1458 | if (signal_pending(current)) { |
1455 | /* return if a signal was received */ | 1459 | /* return if a signal was received */ |
1456 | IVTV_DEBUG_INFO("User stopped wait for event\n"); | 1460 | IVTV_DEBUG_INFO("User stopped wait for event\n"); |
@@ -1580,12 +1584,9 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, | |||
1580 | return 0; | 1584 | return 0; |
1581 | } | 1585 | } |
1582 | 1586 | ||
1583 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 1587 | static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp, |
1584 | unsigned long arg) | 1588 | unsigned int cmd, unsigned long arg) |
1585 | { | 1589 | { |
1586 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1587 | struct ivtv *itv = id->itv; | ||
1588 | |||
1589 | /* Filter dvb ioctls that cannot be handled by video_usercopy */ | 1590 | /* Filter dvb ioctls that cannot be handled by video_usercopy */ |
1590 | switch (cmd) { | 1591 | switch (cmd) { |
1591 | case VIDEO_SELECT_SOURCE: | 1592 | case VIDEO_SELECT_SOURCE: |
@@ -1620,3 +1621,16 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
1620 | } | 1621 | } |
1621 | return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); | 1622 | return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); |
1622 | } | 1623 | } |
1624 | |||
1625 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1626 | unsigned long arg) | ||
1627 | { | ||
1628 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1629 | struct ivtv *itv = id->itv; | ||
1630 | int res; | ||
1631 | |||
1632 | mutex_lock(&itv->serialize_lock); | ||
1633 | res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg); | ||
1634 | mutex_unlock(&itv->serialize_lock); | ||
1635 | return res; | ||
1636 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index fab5c51b1519..65fa247e33c5 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -437,9 +437,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
437 | if (s->v4l2dev == NULL) | 437 | if (s->v4l2dev == NULL) |
438 | return -EINVAL; | 438 | return -EINVAL; |
439 | 439 | ||
440 | /* Big serialization lock to ensure no two streams are started | ||
441 | simultaneously: that can give all sorts of weird results. */ | ||
442 | mutex_lock(&itv->serialize_lock); | ||
443 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); | 440 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); |
444 | 441 | ||
445 | switch (s->type) { | 442 | switch (s->type) { |
@@ -481,7 +478,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
481 | 0, sizeof(itv->vbi.sliced_mpeg_size)); | 478 | 0, sizeof(itv->vbi.sliced_mpeg_size)); |
482 | break; | 479 | break; |
483 | default: | 480 | default: |
484 | mutex_unlock(&itv->serialize_lock); | ||
485 | return -EINVAL; | 481 | return -EINVAL; |
486 | } | 482 | } |
487 | s->subtype = subtype; | 483 | s->subtype = subtype; |
@@ -564,7 +560,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
564 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) | 560 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) |
565 | { | 561 | { |
566 | IVTV_DEBUG_WARN( "Error starting capture!\n"); | 562 | IVTV_DEBUG_WARN( "Error starting capture!\n"); |
567 | mutex_unlock(&itv->serialize_lock); | ||
568 | return -EINVAL; | 563 | return -EINVAL; |
569 | } | 564 | } |
570 | 565 | ||
@@ -580,7 +575,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
580 | 575 | ||
581 | /* you're live! sit back and await interrupts :) */ | 576 | /* you're live! sit back and await interrupts :) */ |
582 | atomic_inc(&itv->capturing); | 577 | atomic_inc(&itv->capturing); |
583 | mutex_unlock(&itv->serialize_lock); | ||
584 | return 0; | 578 | return 0; |
585 | } | 579 | } |
586 | 580 | ||
@@ -751,9 +745,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
751 | stopmode = 1; | 745 | stopmode = 1; |
752 | } | 746 | } |
753 | 747 | ||
754 | /* ensure these actions are done only once */ | ||
755 | mutex_lock(&itv->serialize_lock); | ||
756 | |||
757 | /* end_capture */ | 748 | /* end_capture */ |
758 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ | 749 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ |
759 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); | 750 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); |
@@ -810,7 +801,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
810 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | 801 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); |
811 | 802 | ||
812 | if (atomic_read(&itv->capturing) > 0) { | 803 | if (atomic_read(&itv->capturing) > 0) { |
813 | mutex_unlock(&itv->serialize_lock); | ||
814 | return 0; | 804 | return 0; |
815 | } | 805 | } |
816 | 806 | ||
@@ -827,7 +817,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
827 | } | 817 | } |
828 | 818 | ||
829 | wake_up(&s->waitq); | 819 | wake_up(&s->waitq); |
830 | mutex_unlock(&itv->serialize_lock); | ||
831 | 820 | ||
832 | return 0; | 821 | return 0; |
833 | } | 822 | } |