Commit bfb4d5be authored by Kieran Bingham's avatar Kieran Bingham Committed by Mauro Carvalho Chehab

[media] v4l: vsp1: Repair race between frame end and qbuf handler

The frame-end function releases and completes the buffers on the input
and output entities of the pipe before marking the pipe->state as
'STOPPED'. This introduces a race whereby with the pipe->state still
'RUNNING', a QBUF handler can commence processing a frame before the
frame_end function has completed.

In the event that this happens, a frame queued by QBUF hangs due to the
incorrect pipe->state setting which prevents vsp1_pipeline_run from
issuing a CMD_STRCMD.

By locking the entire function we prevent this from occurring, but we
also change the locking state of the buffer release code. This has been
analysed visually as acceptable, but it must be considered that this now
causes the video->irqlock to be taken under the pipe->irqlock context.
Signed-off-by: default avatarKieran Bingham <kieran+renesas@bingham.xyz>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 7a9e7bd3
...@@ -234,18 +234,13 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, ...@@ -234,18 +234,13 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
{ {
struct vsp1_video *video = rwpf->video; struct vsp1_video *video = rwpf->video;
struct vsp1_vb2_buffer *buf; struct vsp1_vb2_buffer *buf;
unsigned long flags;
buf = vsp1_video_complete_buffer(video); buf = vsp1_video_complete_buffer(video);
if (buf == NULL) if (buf == NULL)
return; return;
spin_lock_irqsave(&pipe->irqlock, flags);
video->rwpf->mem = buf->mem; video->rwpf->mem = buf->mem;
pipe->buffers_ready |= 1 << video->pipe_index; pipe->buffers_ready |= 1 << video->pipe_index;
spin_unlock_irqrestore(&pipe->irqlock, flags);
} }
static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
...@@ -285,6 +280,8 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) ...@@ -285,6 +280,8 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
unsigned long flags; unsigned long flags;
unsigned int i; unsigned int i;
spin_lock_irqsave(&pipe->irqlock, flags);
/* Complete buffers on all video nodes. */ /* Complete buffers on all video nodes. */
for (i = 0; i < vsp1->info->rpf_count; ++i) { for (i = 0; i < vsp1->info->rpf_count; ++i) {
if (!pipe->inputs[i]) if (!pipe->inputs[i])
...@@ -295,8 +292,6 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) ...@@ -295,8 +292,6 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
vsp1_video_frame_end(pipe, pipe->output); vsp1_video_frame_end(pipe, pipe->output);
spin_lock_irqsave(&pipe->irqlock, flags);
state = pipe->state; state = pipe->state;
pipe->state = VSP1_PIPELINE_STOPPED; pipe->state = VSP1_PIPELINE_STOPPED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment