| From a30ea33c0959c27b2069168fec97eeb1c62ea66d Mon Sep 17 00:00:00 2001 |
| From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> |
| 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 <kieran.bingham+renesas@ideasonboard.com> |
| Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> |
| (cherry picked from commit 4461c84b52b4a952c657505ef7e4e06b016783df) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/media/platform/vsp1/vsp1_video.c | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c |
| index 0113a55b19c9..eb422c150847 100644 |
| --- 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(struct vb2_queue *vq, unsigned int count) |
| { |
| 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(struct vb2_queue *vq, unsigned int count) |
| mutex_unlock(&pipe->lock); |
| return ret; |
| } |
| + |
| + start_pipeline = true; |
| } |
| |
| pipe->stream_count++; |
| 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); |
| if (vsp1_pipeline_ready(pipe)) |
| vsp1_video_pipeline_run(pipe); |
| -- |
| 2.13.3 |
| |