aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2007-07-10 13:58:33 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-07-18 13:24:47 -0400
commitf885969196da6ae905162c0d1c5f0553de12cb40 (patch)
tree3d23cbba88366834d05d8b6a63c6889caf789b37
parent0901973f4bde9c1004795c9c2321bdc51f3996f1 (diff)
V4L/DVB (5842): ivtv: Add locking to ensure stream setup is atomic.
Starting an MPEG and VBI capture simultaneously caused errors in the VBI setup: this setup was done twice when it should be done only for the first stream that is opened. Added a mutex to prevent this from happening. 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-driver.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c30
3 files changed, 21 insertions, 11 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 28a53c42020d..ab7c3f6d3531 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -623,6 +623,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
623 itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ 623 itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
624 itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ 624 itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
625 625
626 mutex_init(&itv->serialize_lock);
626 mutex_init(&itv->i2c_bus_lock); 627 mutex_init(&itv->i2c_bus_lock);
627 mutex_init(&itv->udma.lock); 628 mutex_init(&itv->udma.lock);
628 629
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 48afd4270cbf..65ebddab3fe1 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -722,6 +722,7 @@ struct ivtv {
722 int search_pack_header; 722 int search_pack_header;
723 723
724 spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ 724 spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
725 struct mutex serialize_lock; /* lock used to serialize starting streams */
725 726
726 /* User based DMA for OSD */ 727 /* User based DMA for OSD */
727 struct ivtv_user_dma udma; 728 struct ivtv_user_dma udma;
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 6af88ae9295f..d538efaf61c9 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
446 if (s->v4l2dev == NULL) 446 if (s->v4l2dev == NULL)
447 return -EINVAL; 447 return -EINVAL;
448 448
449 /* Big serialization lock to ensure no two streams are started
450 simultaneously: that can give all sorts of weird results. */
451 mutex_lock(&itv->serialize_lock);
449 IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); 452 IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
450 453
451 switch (s->type) { 454 switch (s->type) {
@@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
487 0, sizeof(itv->vbi.sliced_mpeg_size)); 490 0, sizeof(itv->vbi.sliced_mpeg_size));
488 break; 491 break;
489 default: 492 default:
493 mutex_unlock(&itv->serialize_lock);
490 return -EINVAL; 494 return -EINVAL;
491 } 495 }
492 s->subtype = subtype; 496 s->subtype = subtype;
@@ -568,6 +572,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
568 if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) 572 if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
569 { 573 {
570 IVTV_DEBUG_WARN( "Error starting capture!\n"); 574 IVTV_DEBUG_WARN( "Error starting capture!\n");
575 mutex_unlock(&itv->serialize_lock);
571 return -EINVAL; 576 return -EINVAL;
572 } 577 }
573 578
@@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
583 588
584 /* you're live! sit back and await interrupts :) */ 589 /* you're live! sit back and await interrupts :) */
585 atomic_inc(&itv->capturing); 590 atomic_inc(&itv->capturing);
591 mutex_unlock(&itv->serialize_lock);
586 return 0; 592 return 0;
587} 593}
588 594
@@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
762 /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ 768 /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
763 ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); 769 ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
764 770
765 /* only run these if we're shutting down the last cap */
766 if (atomic_read(&itv->capturing) - 1 == 0) {
767 /* event notification (off) */
768 if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
769 /* type: 0 = refresh */
770 /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
771 ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
772 ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
773 }
774 }
775
776 then = jiffies; 771 then = jiffies;
777 772
778 if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { 773 if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
@@ -840,17 +835,30 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
840 /* Clear capture and no-read bits */ 835 /* Clear capture and no-read bits */
841 clear_bit(IVTV_F_S_STREAMING, &s->s_flags); 836 clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
842 837
838 /* ensure these global cleanup actions are done only once */
839 mutex_lock(&itv->serialize_lock);
840
843 if (s->type == IVTV_ENC_STREAM_TYPE_VBI) 841 if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
844 ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); 842 ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
845 843
846 if (atomic_read(&itv->capturing) > 0) { 844 if (atomic_read(&itv->capturing) > 0) {
845 mutex_unlock(&itv->serialize_lock);
847 return 0; 846 return 0;
848 } 847 }
849 848
850 /* Set the following Interrupt mask bits for capture */ 849 /* Set the following Interrupt mask bits for capture */
851 ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); 850 ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
852 851
852 /* event notification (off) */
853 if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
854 /* type: 0 = refresh */
855 /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
856 ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
857 ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
858 }
859
853 wake_up(&s->waitq); 860 wake_up(&s->waitq);
861 mutex_unlock(&itv->serialize_lock);
854 862
855 return 0; 863 return 0;
856} 864}