Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8859691 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 0901973f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -623,6 +623,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
	itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
	itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */

	mutex_init(&itv->serialize_lock);
	mutex_init(&itv->i2c_bus_lock);
	mutex_init(&itv->udma.lock);

+1 −0
Original line number Diff line number Diff line
@@ -722,6 +722,7 @@ struct ivtv {
	int search_pack_header;

	spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
	struct mutex serialize_lock;  /* lock used to serialize starting streams */

	/* User based DMA for OSD */
	struct ivtv_user_dma udma;
+19 −11
Original line number Diff line number Diff line
@@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
	if (s->v4l2dev == NULL)
		return -EINVAL;

	/* Big serialization lock to ensure no two streams are started
	   simultaneously: that can give all sorts of weird results. */
	mutex_lock(&itv->serialize_lock);
	IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);

	switch (s->type) {
@@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
			0, sizeof(itv->vbi.sliced_mpeg_size));
		break;
	default:
		mutex_unlock(&itv->serialize_lock);
		return -EINVAL;
	}
	s->subtype = subtype;
@@ -568,6 +572,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
	if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
	{
		IVTV_DEBUG_WARN( "Error starting capture!\n");
		mutex_unlock(&itv->serialize_lock);
		return -EINVAL;
	}

@@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)

	/* you're live! sit back and await interrupts :) */
	atomic_inc(&itv->capturing);
	mutex_unlock(&itv->serialize_lock);
	return 0;
}

@@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
	/* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);

	/* only run these if we're shutting down the last cap */
	if (atomic_read(&itv->capturing) - 1 == 0) {
		/* event notification (off) */
		if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
			/* type: 0 = refresh */
			/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
			ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
			ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
		}
	}

	then = jiffies;

	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)
	/* Clear capture and no-read bits */
	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);

	/* ensure these global cleanup actions are done only once */
	mutex_lock(&itv->serialize_lock);

	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);

	if (atomic_read(&itv->capturing) > 0) {
		mutex_unlock(&itv->serialize_lock);
		return 0;
	}

	/* Set the following Interrupt mask bits for capture */
	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);

	/* event notification (off) */
	if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
		/* type: 0 = refresh */
		/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
	}

	wake_up(&s->waitq);
	mutex_unlock(&itv->serialize_lock);

	return 0;
}