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

[media] v4l: vsp1: Prevent multiple streamon race commencing pipeline early

With multiple inputs through the BRU it is feasible for the streams to
race each other at stream-on.

Multiple VIDIOC_STREAMON calls racing each other could have process
N-1 skipping over the pipeline setup section and then start the pipeline
early, if videobuf2 has already enqueued buffers to the driver for
process N but not called the .start_streaming() operation yet

In the case of the video pipelines, this
can present two serious issues.

 1) A null-dereference if the pipe->dl is committed at the same time as
    the vsp1_video_setup_pipeline() is processing

 2) A hardware hang, where a display list is committed without having
    called vsp1_video_setup_pipeline() first

Repair this issue, by ensuring that only the stream which configures the
pipeline is able to start it.
Signed-off-by: default avatarKieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 34253822
...@@ -797,6 +797,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -797,6 +797,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
{ {
struct vsp1_video *video = vb2_get_drv_priv(vq); struct vsp1_video *video = vb2_get_drv_priv(vq);
struct vsp1_pipeline *pipe = video->rwpf->pipe; struct vsp1_pipeline *pipe = video->rwpf->pipe;
bool start_pipeline = false;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -807,11 +808,23 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) ...@@ -807,11 +808,23 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
mutex_unlock(&pipe->lock); mutex_unlock(&pipe->lock);
return ret; return ret;
} }
start_pipeline = true;
} }
pipe->stream_count++; pipe->stream_count++;
mutex_unlock(&pipe->lock); mutex_unlock(&pipe->lock);
/*
* vsp1_pipeline_ready() is not sufficient to establish that all streams
* are prepared and the pipeline is configured, as multiple streams
* can race through streamon with buffers already queued; Therefore we
* don't even attempt to start the pipeline until the last stream has
* called through here.
*/
if (!start_pipeline)
return 0;
spin_lock_irqsave(&pipe->irqlock, flags); spin_lock_irqsave(&pipe->irqlock, flags);
if (vsp1_pipeline_ready(pipe)) if (vsp1_pipeline_ready(pipe))
vsp1_video_pipeline_run(pipe); vsp1_video_pipeline_run(pipe);
......
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