aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2007-08-19 06:10:55 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:05:43 -0400
commitbaa4072d84e7a2e9954121c826d7bb8f1fb66b38 (patch)
tree0b354b98963f39c3089e9c5729d40b1d3a0d231c
parent1aa32c2ffd146dddd76babf842e998502f1b993a (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.c95
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c26
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c11
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
828int ivtv_v4l2_open(struct inode *inode, struct file *filp) 837static 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
916int 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
938void ivtv_mute(struct ivtv *itv) 955void 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
1583int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 1587static 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
1625int 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}