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

Commit 2bd7ac55 authored by Ian Armstrong's avatar Ian Armstrong Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (9166): ivtv - Fix potential race condition in yuv handler



Modified yuv register update handling to remove a potential race condition
which could occur with the first video frame.

Also removed a forced yuv position update, since changing the source video
dimensions or interlace settings doesn't affect the frame already being
displayed.

Signed-off-by: default avatarIan Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ec9faa1c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -506,6 +506,8 @@ struct yuv_playback_info
	struct v4l2_rect main_rect;
	u32 v4l2_src_w;
	u32 v4l2_src_h;

	u8 running; /* Have any frames been displayed */
};

#define IVTV_VBI_FRAMES 32
+0 −2
Original line number Diff line number Diff line
@@ -644,8 +644,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
		itv->dma_data_req_size =
			1080 * ((yi->v4l2_src_h + 31) & ~31);

	/* Force update of yuv registers */
	yi->yuv_forced_update = 1;
	return 0;
}

+6 −3
Original line number Diff line number Diff line
@@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
	 */
	unsigned int frame = read_reg(0x28c0) & 1;
	struct yuv_playback_info *yi = &itv->yuv_info;
	int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame);
	int last_dma_frame = atomic_read(&yi->next_dma_frame);
	struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];

	if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
@@ -772,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
				next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
				atomic_set(&yi->next_dma_frame, next_dma_frame);
				yi->fields_lapsed = -1;
				yi->running = 1;
			}
		}
	}
@@ -804,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv)
		}

		/* Check if we need to update the yuv registers */
		if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) {
		if (yi->running && (yi->yuv_forced_update || f->update)) {
			if (!f->update) {
				last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS;
				last_dma_frame =
					(u8)(atomic_read(&yi->next_dma_frame) -
						 1) % IVTV_YUV_BUFFERS;
				f = &yi->new_frame_info[last_dma_frame];
			}

+1 −0
Original line number Diff line number Diff line
@@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv)
	IVTV_DEBUG_YUV("ivtv_yuv_close\n");
	ivtv_waitq(&itv->vsync_waitq);

	yi->running = 0;
	atomic_set(&yi->next_dma_frame, -1);
	atomic_set(&yi->next_fill_frame, 0);