mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
staging: media: ipu3: Stop streaming in inverse order of starting
imgu_vb2_stop_streaming() did not order shutdown items in the inverse order and count of what imgu_vb2_start_streaming() does. Consequently, v6.7's new WARN_ON in call_s_stream() started screaming because it was called multiple times on the entire pipe, yet it should only be called when the pipe is interrupted by any first node being taken offline. This reorders streamoff to be the inverse of streamon, and uses analogous conditions to decide when and how often to call additional teardown functions. v4l2_subdev_call(s_stream, 0) remains outside the streaming_lock, analogously to imgu_vb2_start_streaming(). Signed-off-by: Max Staudt <mstaudt@chromium.org> Reviewed-by: Bingbu Cao <bingbu.cao@intel.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
parent
cf27c5a1bd
commit
5256cfec79
@ -535,29 +535,51 @@ static void imgu_vb2_stop_streaming(struct vb2_queue *vq)
|
||||
container_of(vq, struct imgu_video_device, vbq);
|
||||
int r;
|
||||
unsigned int pipe;
|
||||
bool stop_streaming = false;
|
||||
|
||||
/* Verify that the node had been setup with imgu_v4l2_node_setup() */
|
||||
WARN_ON(!node->enabled);
|
||||
|
||||
pipe = node->pipe;
|
||||
dev_dbg(dev, "Try to stream off node [%u][%u]", pipe, node->id);
|
||||
imgu_pipe = &imgu->imgu_pipe[pipe];
|
||||
r = v4l2_subdev_call(&imgu_pipe->imgu_sd.subdev, video, s_stream, 0);
|
||||
if (r)
|
||||
dev_err(&imgu->pci_dev->dev,
|
||||
"failed to stop subdev streaming\n");
|
||||
|
||||
/*
|
||||
* When the first node of a streaming setup is stopped, the entire
|
||||
* pipeline needs to stop before individual nodes are disabled.
|
||||
* Perform the inverse of the initial setup.
|
||||
*
|
||||
* Part 1 - s_stream on the entire pipeline
|
||||
*/
|
||||
mutex_lock(&imgu->streaming_lock);
|
||||
/* Was this the first node with streaming disabled? */
|
||||
if (imgu->streaming) {
|
||||
/* Yes, really stop streaming now */
|
||||
dev_dbg(dev, "IMGU streaming is ready to stop");
|
||||
r = imgu_s_stream(imgu, false);
|
||||
if (!r)
|
||||
imgu->streaming = false;
|
||||
stop_streaming = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&imgu->streaming_lock);
|
||||
|
||||
/* Part 2 - s_stream on subdevs
|
||||
*
|
||||
* If we call s_stream multiple times, Linux v6.7's call_s_stream()
|
||||
* WARNs and aborts. Thus, disable all pipes at once, and only once.
|
||||
*/
|
||||
if (stop_streaming) {
|
||||
for_each_set_bit(pipe, imgu->css.enabled_pipes,
|
||||
IMGU_MAX_PIPE_NUM) {
|
||||
imgu_pipe = &imgu->imgu_pipe[pipe];
|
||||
|
||||
r = v4l2_subdev_call(&imgu_pipe->imgu_sd.subdev,
|
||||
video, s_stream, 0);
|
||||
if (r)
|
||||
dev_err(&imgu->pci_dev->dev,
|
||||
"failed to stop subdev streaming\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Part 3 - individual node teardown */
|
||||
video_device_pipeline_stop(&node->vdev);
|
||||
imgu_return_all_buffers(imgu, node, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user