blob: e8cd34d400733c6b3f8f86d5f308178e0e5d1fc3 [file] [log] [blame]
From a30ea33c0959c27b2069168fec97eeb1c62ea66d Mon Sep 17 00:00:00 2001
From: Kieran Bingham <>
Date: Fri, 6 Jan 2017 10:15:28 -0200
Subject: [PATCH 142/286] [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: Kieran Bingham <>
Reviewed-by: Laurent Pinchart <>
Signed-off-by: Mauro Carvalho Chehab <>
(cherry picked from commit 4461c84b52b4a952c657505ef7e4e06b016783df)
Signed-off-by: Simon Horman <>
drivers/media/platform/vsp1/vsp1_video.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -797,6 +797,7 @@ static int vsp1_video_start_streaming(st
struct vsp1_video *video = vb2_get_drv_priv(vq);
struct vsp1_pipeline *pipe = video->rwpf->pipe;
+ bool start_pipeline = false;
unsigned long flags;
int ret;
@@ -807,11 +808,23 @@ static int vsp1_video_start_streaming(st
return ret;
+ start_pipeline = true;
+ /*
+ * 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);
if (vsp1_pipeline_ready(pipe))