Max, Thanks for your patch. On 6/20/24 10:45 PM, Max Staudt wrote: > 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@xxxxxxxxxxxx> > --- > drivers/staging/media/ipu3/ipu3-v4l2.c | 36 +++++++++++++++++++++----- > 1 file changed, 29 insertions(+), 7 deletions(-) > > diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c > index 3ff390b04e1a..e7aee7e3db5b 100644 > --- a/drivers/staging/media/ipu3/ipu3-v4l2.c > +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c > @@ -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"); I guess the subdev streams API can help us on this, but current fix looks fine for me. > > + /* > + * 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 stream on or off? it is a little confusing. > + */ > 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"); > + } Is it possible to move this loop into 'if (imgu->streaming)' above? > + } > + > + /* Part 3 - individual node teardown */ > video_device_pipeline_stop(&node->vdev); > imgu_return_all_buffers(imgu, node, VB2_BUF_STATE_ERROR); > } > -- Best regards, Bingbu Cao