diff mbox series

[v3,5/9] media: vimc: Separate closing of stream and thread

Message ID 20200819180442.11630-6-kgupta@es.iitr.ac.in (mailing list archive)
State New, archived
Headers show
Series media: vimc: Multiple stream support in vimc | expand

Commit Message

Kaaira Gupta Aug. 19, 2020, 6:04 p.m. UTC
Make separate functions for stopping streaming of entities in path of a
particular stream and stopping thread. This is needed to ensure that
thread doesn't stop when one device stops streaming in case of multiple
streams.

Signed-off-by: Kaaira Gupta <kgupta@es.iitr.ac.in>
---
 .../media/test-drivers/vimc/vimc-streamer.c   | 82 ++++++++++++-------
 1 file changed, 52 insertions(+), 30 deletions(-)

Comments

Kieran Bingham Sept. 2, 2020, 10:13 a.m. UTC | #1
Hi Kaaira,

On 19/08/2020 19:04, Kaaira Gupta wrote:
> Make separate functions for stopping streaming of entities in path of a
> particular stream and stopping thread. This is needed to ensure that
> thread doesn't stop when one device stops streaming in case of multiple
> streams.
> 
> Signed-off-by: Kaaira Gupta <kgupta@es.iitr.ac.in>
> ---
>  .../media/test-drivers/vimc/vimc-streamer.c   | 82 ++++++++++++-------
>  1 file changed, 52 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
> index cc40ecabe95a..6b5ea1537952 100644
> --- a/drivers/media/test-drivers/vimc/vimc-streamer.c
> +++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
> @@ -13,29 +13,59 @@
>  #include "vimc-streamer.h"
>  
>  /**
> - * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream
> + * vimc_streamer_pipeline_terminate - Terminate the thread
>   *
> - * @stream: the pointer to the stream structure with the pipeline to be
> - *	    disabled.
> + * @stream: the pointer to the stream structure
>   *
> - * Calls s_stream to disable the stream in each entity of the pipeline
> + * Erases values of stream struct and terminates the thread

It would help if the function brief described it's purpose rather than
'what it does'. "Erases values of stream struct" is not helpful here, as
that's just a direct read of what happens in the code.

I'm guessing here, but how about:

"Tear down all resources belonging to the pipeline when there are no
longer any active streams being used. This includes stopping the active
processing thread"


But reading my text makes me worry about the ordering that might take
place. The thread should be stopped as soon as the last stream using it
is stopped. Presumably as the 'first thing' that happens to make sure
there is no concurrent processing while the stream is being disabled.

Hopefully there's no race condition ...


>   *
>   */
>  static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
>  {
>  	struct vimc_ent_device *ved;
> -	struct v4l2_subdev *sd;
>  
>  	while (stream->pipe_size) {
>  		stream->pipe_size--;
>  		ved = stream->ved_pipeline[stream->pipe_size];
>  		stream->ved_pipeline[stream->pipe_size] = NULL;
> +	}
>  
> -		if (!is_media_entity_v4l2_subdev(ved->ent))
> -			continue;
> +	kthread_stop(stream->kthread);
> +	stream->kthread = NULL;
> +}
>  
> -		sd = media_entity_to_v4l2_subdev(ved->ent);
> -		v4l2_subdev_call(sd, video, s_stream, 0);
> +/**
> + * vimc_streamer_stream_terminate - Disable stream in all ved in stream
> + *
> + * @ved: pointer to the ved for which stream needs to be disabled
> + *
> + * Calls s_stream to disable the stream in each entity of the stream
> + *
> + */
> +static void vimc_streamer_stream_terminate(struct vimc_ent_device *ved)

I would call this vimc_streamer_stream_stop to match
vimc_streamer_stream_start() rather than terminate...

> +{
> +	struct media_entity *entity = ved->ent;
> +	struct video_device *vdev;
> +	struct v4l2_subdev *sd;
> +
> +	while (entity) {
> +		if (is_media_entity_v4l2_subdev(ved->ent)) {
> +			sd = media_entity_to_v4l2_subdev(ved->ent);
> +			v4l2_subdev_call(sd, video, s_stream, 0);
> +		}
> +		entity = vimc_get_source_entity(ved->ent);
> +		if (!entity)
> +			break;
> +
> +		if (is_media_entity_v4l2_subdev(entity)) {
> +			sd = media_entity_to_v4l2_subdev(entity);
> +			ved = v4l2_get_subdevdata(sd);
> +		} else {
> +			vdev = container_of(entity,
> +					    struct video_device,
> +					    entity);
> +			ved = video_get_drvdata(vdev);
> +		}

It looks like this is walking back through the linked graph, calling
s_stream(0) right?

I wonder if struct vimc_ent_device should have a pointer to the entity
it's connected to, to simplify this. ... presumably this is done
elsewhere too?

Although then that's still walking 'backwards' rather than forwards...




>  	}
>  }
>  
> @@ -43,25 +73,25 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
>   * vimc_streamer_stream_start - Starts streaming for all entities
>   * in a stream
>   *
> - * @ved:    the pointer to the vimc entity initializing the stream
> + * @cved:    the pointer to the vimc entity initializing the stream
>   *
>   * Walks through the entity graph to call vimc_streamer_s_stream()
>   * to enable stream in all entities in path of a stream.
>   *
>   * Return: 0 if success, error code otherwise.
>   */
> -static int vimc_streamer_stream_start(struct vimc_stream *stream,
> -				      struct vimc_ent_device *ved)
> +static int vimc_streamer_stream_start(struct vimc_ent_device *cved)
>  {
>  	struct media_entity *entity;
>  	struct video_device *vdev;
>  	struct v4l2_subdev *sd;
> +	struct vimc_ent_device *ved = cved;
>  	int stream_size = 0;
>  	int ret = 0;
>  
>  	while (stream_size < VIMC_STREAMER_PIPELINE_MAX_SIZE) {
>  		if (!ved) {
> -			vimc_streamer_pipeline_terminate(stream);
> +			vimc_streamer_stream_terminate(cved);
>  			return -EINVAL;
>  		}
>  
> @@ -71,7 +101,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
>  			if (ret && ret != -ENOIOCTLCMD) {
>  				dev_err(ved->dev, "subdev_call error %s\n",
>  					ved->ent->name);
> -				vimc_streamer_pipeline_terminate(stream);
> +				vimc_streamer_stream_terminate(cved);
>  				return ret;
>  			}
>  		}
> @@ -84,7 +114,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
>  				dev_err(ved->dev,
>  					"first entity in the pipe '%s' is not a source\n",
>  					ved->ent->name);
> -				vimc_streamer_pipeline_terminate(stream);
> +				vimc_streamer_stream_terminate(cved);
>  				pr_info ("first entry not source");
>  				return -EPIPE;
>  			}
> @@ -104,7 +134,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
>  		stream_size++;
>  	}
>  
> -	vimc_streamer_pipeline_terminate(stream);
> +	vimc_streamer_stream_terminate(cved);
>  	return -EINVAL;
>  }
>  
> @@ -120,13 +150,14 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
>   * Return: 0 if success, error code otherwise.
>   */
>  static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
> -				       struct vimc_ent_device *ved)
> +				       struct vimc_ent_device *cved)
>  {
>  	struct media_entity *entity;
>  	struct media_device *mdev;
>  	struct media_graph graph;
>  	struct video_device *vdev;
>  	struct v4l2_subdev *sd;
> +	struct vimc_ent_device *ved = cved;
>  	int ret;
>  
>  	entity = ved->ent;
> @@ -170,6 +201,7 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
>  		}
>  	}
>  
> +	vimc_streamer_stream_terminate(cved);
>  	vimc_streamer_pipeline_terminate(stream);
>  	return -EINVAL;
>  }
> @@ -246,7 +278,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
>  		if (stream->kthread)
>  			return 0;
>  
> -		ret = vimc_streamer_stream_start(stream, ved);
> +		ret = vimc_streamer_stream_start(ved);
>  		if (ret)
>  			return ret;
>  
> @@ -260,6 +292,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
>  		if (IS_ERR(stream->kthread)) {
>  			ret = PTR_ERR(stream->kthread);
>  			dev_err(ved->dev, "kthread_run failed with %d\n", ret);
> +			vimc_streamer_stream_terminate(ved);
>  			vimc_streamer_pipeline_terminate(stream);
>  			stream->kthread = NULL;

If vimc_streamer_pipeline_terminate() sets stream->kthread = NULL, it
doesn't need to be done again here.


>  			return ret;
> @@ -269,18 +302,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
>  		if (!stream->kthread)
>  			return 0;
>  
> -		ret = kthread_stop(stream->kthread);
> -		/*
> -		 * kthread_stop returns -EINTR in cases when streamon was
> -		 * immediately followed by streamoff, and the thread didn't had
> -		 * a chance to run. Ignore errors to stop the stream in the
> -		 * pipeline.
> -		 */

Do we need to retain that comment when stopping the thread?

> -		if (ret)
> -			dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
> -
> -		stream->kthread = NULL;
> -
> +		vimc_streamer_stream_terminate(ved);
>  		vimc_streamer_pipeline_terminate(stream);
>  	}
>  
>
Kaaira Gupta Sept. 12, 2020, 10:28 a.m. UTC | #2
Hi,

On Wed, Sep 02, 2020 at 11:13:09AM +0100, Kieran Bingham wrote:
> Hi Kaaira,
> 
> On 19/08/2020 19:04, Kaaira Gupta wrote:
> > Make separate functions for stopping streaming of entities in path of a
> > particular stream and stopping thread. This is needed to ensure that
> > thread doesn't stop when one device stops streaming in case of multiple
> > streams.
> > 
> > Signed-off-by: Kaaira Gupta <kgupta@es.iitr.ac.in>
> > ---
> >  .../media/test-drivers/vimc/vimc-streamer.c   | 82 ++++++++++++-------
> >  1 file changed, 52 insertions(+), 30 deletions(-)
> > 
> > diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
> > index cc40ecabe95a..6b5ea1537952 100644
> > --- a/drivers/media/test-drivers/vimc/vimc-streamer.c
> > +++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
> > @@ -13,29 +13,59 @@
> >  #include "vimc-streamer.h"
> >  
> >  /**
> > - * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream
> > + * vimc_streamer_pipeline_terminate - Terminate the thread
> >   *
> > - * @stream: the pointer to the stream structure with the pipeline to be
> > - *	    disabled.
> > + * @stream: the pointer to the stream structure
> >   *
> > - * Calls s_stream to disable the stream in each entity of the pipeline
> > + * Erases values of stream struct and terminates the thread
> 
> It would help if the function brief described it's purpose rather than
> 'what it does'. "Erases values of stream struct" is not helpful here, as
> that's just a direct read of what happens in the code.

Okay, I will make these changes

> 
> I'm guessing here, but how about:
> 
> "Tear down all resources belonging to the pipeline when there are no
> longer any active streams being used. This includes stopping the active
> processing thread"
> 
> 
> But reading my text makes me worry about the ordering that might take
> place. The thread should be stopped as soon as the last stream using it
> is stopped. Presumably as the 'first thing' that happens to make sure
> there is no concurrent processing while the stream is being disabled.
> 
> Hopefully there's no race condition ...

There isn't..in further patches (when multiple streams are allowed),
pipeline_terminate is called only after both the streams terminate.

> 
> 
> >   *
> >   */
> >  static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
> >  {
> >  	struct vimc_ent_device *ved;
> > -	struct v4l2_subdev *sd;
> >  
> >  	while (stream->pipe_size) {
> >  		stream->pipe_size--;
> >  		ved = stream->ved_pipeline[stream->pipe_size];
> >  		stream->ved_pipeline[stream->pipe_size] = NULL;
> > +	}
> >  
> > -		if (!is_media_entity_v4l2_subdev(ved->ent))
> > -			continue;
> > +	kthread_stop(stream->kthread);
> > +	stream->kthread = NULL;
> > +}
> >  
> > -		sd = media_entity_to_v4l2_subdev(ved->ent);
> > -		v4l2_subdev_call(sd, video, s_stream, 0);
> > +/**
> > + * vimc_streamer_stream_terminate - Disable stream in all ved in stream
> > + *
> > + * @ved: pointer to the ved for which stream needs to be disabled
> > + *
> > + * Calls s_stream to disable the stream in each entity of the stream
> > + *
> > + */
> > +static void vimc_streamer_stream_terminate(struct vimc_ent_device *ved)
> 
> I would call this vimc_streamer_stream_stop to match
> vimc_streamer_stream_start() rather than terminate...

Okay, noted..I will make this change

> 
> > +{
> > +	struct media_entity *entity = ved->ent;
> > +	struct video_device *vdev;
> > +	struct v4l2_subdev *sd;
> > +
> > +	while (entity) {
> > +		if (is_media_entity_v4l2_subdev(ved->ent)) {
> > +			sd = media_entity_to_v4l2_subdev(ved->ent);
> > +			v4l2_subdev_call(sd, video, s_stream, 0);
> > +		}
> > +		entity = vimc_get_source_entity(ved->ent);
> > +		if (!entity)
> > +			break;
> > +
> > +		if (is_media_entity_v4l2_subdev(entity)) {
> > +			sd = media_entity_to_v4l2_subdev(entity);
> > +			ved = v4l2_get_subdevdata(sd);
> > +		} else {
> > +			vdev = container_of(entity,
> > +					    struct video_device,
> > +					    entity);
> > +			ved = video_get_drvdata(vdev);
> > +		}
> 
> It looks like this is walking back through the linked graph, calling
> s_stream(0) right?

Yes

> 
> I wonder if struct vimc_ent_device should have a pointer to the entity
> it's connected to, to simplify this. ... presumably this is done
> elsewhere too?
> 
> Although then that's still walking 'backwards' rather than forwards...

I don't understand your concern here

> 
> 
> 
> 
> >  	}
> >  }
> >  
> > @@ -43,25 +73,25 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
> >   * vimc_streamer_stream_start - Starts streaming for all entities
> >   * in a stream
> >   *
> > - * @ved:    the pointer to the vimc entity initializing the stream
> > + * @cved:    the pointer to the vimc entity initializing the stream
> >   *
> >   * Walks through the entity graph to call vimc_streamer_s_stream()
> >   * to enable stream in all entities in path of a stream.
> >   *
> >   * Return: 0 if success, error code otherwise.
> >   */
> > -static int vimc_streamer_stream_start(struct vimc_stream *stream,
> > -				      struct vimc_ent_device *ved)
> > +static int vimc_streamer_stream_start(struct vimc_ent_device *cved)
> >  {
> >  	struct media_entity *entity;
> >  	struct video_device *vdev;
> >  	struct v4l2_subdev *sd;
> > +	struct vimc_ent_device *ved = cved;
> >  	int stream_size = 0;
> >  	int ret = 0;
> >  
> >  	while (stream_size < VIMC_STREAMER_PIPELINE_MAX_SIZE) {
> >  		if (!ved) {
> > -			vimc_streamer_pipeline_terminate(stream);
> > +			vimc_streamer_stream_terminate(cved);
> >  			return -EINVAL;
> >  		}
> >  
> > @@ -71,7 +101,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
> >  			if (ret && ret != -ENOIOCTLCMD) {
> >  				dev_err(ved->dev, "subdev_call error %s\n",
> >  					ved->ent->name);
> > -				vimc_streamer_pipeline_terminate(stream);
> > +				vimc_streamer_stream_terminate(cved);
> >  				return ret;
> >  			}
> >  		}
> > @@ -84,7 +114,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
> >  				dev_err(ved->dev,
> >  					"first entity in the pipe '%s' is not a source\n",
> >  					ved->ent->name);
> > -				vimc_streamer_pipeline_terminate(stream);
> > +				vimc_streamer_stream_terminate(cved);
> >  				pr_info ("first entry not source");
> >  				return -EPIPE;
> >  			}
> > @@ -104,7 +134,7 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
> >  		stream_size++;
> >  	}
> >  
> > -	vimc_streamer_pipeline_terminate(stream);
> > +	vimc_streamer_stream_terminate(cved);
> >  	return -EINVAL;
> >  }
> >  
> > @@ -120,13 +150,14 @@ static int vimc_streamer_stream_start(struct vimc_stream *stream,
> >   * Return: 0 if success, error code otherwise.
> >   */
> >  static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
> > -				       struct vimc_ent_device *ved)
> > +				       struct vimc_ent_device *cved)
> >  {
> >  	struct media_entity *entity;
> >  	struct media_device *mdev;
> >  	struct media_graph graph;
> >  	struct video_device *vdev;
> >  	struct v4l2_subdev *sd;
> > +	struct vimc_ent_device *ved = cved;
> >  	int ret;
> >  
> >  	entity = ved->ent;
> > @@ -170,6 +201,7 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
> >  		}
> >  	}
> >  
> > +	vimc_streamer_stream_terminate(cved);
> >  	vimc_streamer_pipeline_terminate(stream);
> >  	return -EINVAL;
> >  }
> > @@ -246,7 +278,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
> >  		if (stream->kthread)
> >  			return 0;
> >  
> > -		ret = vimc_streamer_stream_start(stream, ved);
> > +		ret = vimc_streamer_stream_start(ved);
> >  		if (ret)
> >  			return ret;
> >  
> > @@ -260,6 +292,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
> >  		if (IS_ERR(stream->kthread)) {
> >  			ret = PTR_ERR(stream->kthread);
> >  			dev_err(ved->dev, "kthread_run failed with %d\n", ret);
> > +			vimc_streamer_stream_terminate(ved);
> >  			vimc_streamer_pipeline_terminate(stream);
> >  			stream->kthread = NULL;
> 
> If vimc_streamer_pipeline_terminate() sets stream->kthread = NULL, it
> doesn't need to be done again here.

Noted

> 
> 
> >  			return ret;
> > @@ -269,18 +302,7 @@ int vimc_streamer_s_stream(struct vimc_stream *stream,
> >  		if (!stream->kthread)
> >  			return 0;
> >  
> > -		ret = kthread_stop(stream->kthread);
> > -		/*
> > -		 * kthread_stop returns -EINTR in cases when streamon was
> > -		 * immediately followed by streamoff, and the thread didn't had
> > -		 * a chance to run. Ignore errors to stop the stream in the
> > -		 * pipeline.
> > -		 */
> 
> Do we need to retain that comment when stopping the thread?

I am not sure, I think helen or dafna can help?

> 
> > -		if (ret)
> > -			dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
> > -
> > -		stream->kthread = NULL;
> > -
> > +		vimc_streamer_stream_terminate(ved);
> >  		vimc_streamer_pipeline_terminate(stream);
> >  	}
> >  
> > 
> 
> -- 
> Regards
> --
> Kieran
diff mbox series

Patch

diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
index cc40ecabe95a..6b5ea1537952 100644
--- a/drivers/media/test-drivers/vimc/vimc-streamer.c
+++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
@@ -13,29 +13,59 @@ 
 #include "vimc-streamer.h"
 
 /**
- * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream
+ * vimc_streamer_pipeline_terminate - Terminate the thread
  *
- * @stream: the pointer to the stream structure with the pipeline to be
- *	    disabled.
+ * @stream: the pointer to the stream structure
  *
- * Calls s_stream to disable the stream in each entity of the pipeline
+ * Erases values of stream struct and terminates the thread
  *
  */
 static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
 {
 	struct vimc_ent_device *ved;
-	struct v4l2_subdev *sd;
 
 	while (stream->pipe_size) {
 		stream->pipe_size--;
 		ved = stream->ved_pipeline[stream->pipe_size];
 		stream->ved_pipeline[stream->pipe_size] = NULL;
+	}
 
-		if (!is_media_entity_v4l2_subdev(ved->ent))
-			continue;
+	kthread_stop(stream->kthread);
+	stream->kthread = NULL;
+}
 
-		sd = media_entity_to_v4l2_subdev(ved->ent);
-		v4l2_subdev_call(sd, video, s_stream, 0);
+/**
+ * vimc_streamer_stream_terminate - Disable stream in all ved in stream
+ *
+ * @ved: pointer to the ved for which stream needs to be disabled
+ *
+ * Calls s_stream to disable the stream in each entity of the stream
+ *
+ */
+static void vimc_streamer_stream_terminate(struct vimc_ent_device *ved)
+{
+	struct media_entity *entity = ved->ent;
+	struct video_device *vdev;
+	struct v4l2_subdev *sd;
+
+	while (entity) {
+		if (is_media_entity_v4l2_subdev(ved->ent)) {
+			sd = media_entity_to_v4l2_subdev(ved->ent);
+			v4l2_subdev_call(sd, video, s_stream, 0);
+		}
+		entity = vimc_get_source_entity(ved->ent);
+		if (!entity)
+			break;
+
+		if (is_media_entity_v4l2_subdev(entity)) {
+			sd = media_entity_to_v4l2_subdev(entity);
+			ved = v4l2_get_subdevdata(sd);
+		} else {
+			vdev = container_of(entity,
+					    struct video_device,
+					    entity);
+			ved = video_get_drvdata(vdev);
+		}
 	}
 }
 
@@ -43,25 +73,25 @@  static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
  * vimc_streamer_stream_start - Starts streaming for all entities
  * in a stream
  *
- * @ved:    the pointer to the vimc entity initializing the stream
+ * @cved:    the pointer to the vimc entity initializing the stream
  *
  * Walks through the entity graph to call vimc_streamer_s_stream()
  * to enable stream in all entities in path of a stream.
  *
  * Return: 0 if success, error code otherwise.
  */
-static int vimc_streamer_stream_start(struct vimc_stream *stream,
-				      struct vimc_ent_device *ved)
+static int vimc_streamer_stream_start(struct vimc_ent_device *cved)
 {
 	struct media_entity *entity;
 	struct video_device *vdev;
 	struct v4l2_subdev *sd;
+	struct vimc_ent_device *ved = cved;
 	int stream_size = 0;
 	int ret = 0;
 
 	while (stream_size < VIMC_STREAMER_PIPELINE_MAX_SIZE) {
 		if (!ved) {
-			vimc_streamer_pipeline_terminate(stream);
+			vimc_streamer_stream_terminate(cved);
 			return -EINVAL;
 		}
 
@@ -71,7 +101,7 @@  static int vimc_streamer_stream_start(struct vimc_stream *stream,
 			if (ret && ret != -ENOIOCTLCMD) {
 				dev_err(ved->dev, "subdev_call error %s\n",
 					ved->ent->name);
-				vimc_streamer_pipeline_terminate(stream);
+				vimc_streamer_stream_terminate(cved);
 				return ret;
 			}
 		}
@@ -84,7 +114,7 @@  static int vimc_streamer_stream_start(struct vimc_stream *stream,
 				dev_err(ved->dev,
 					"first entity in the pipe '%s' is not a source\n",
 					ved->ent->name);
-				vimc_streamer_pipeline_terminate(stream);
+				vimc_streamer_stream_terminate(cved);
 				pr_info ("first entry not source");
 				return -EPIPE;
 			}
@@ -104,7 +134,7 @@  static int vimc_streamer_stream_start(struct vimc_stream *stream,
 		stream_size++;
 	}
 
-	vimc_streamer_pipeline_terminate(stream);
+	vimc_streamer_stream_terminate(cved);
 	return -EINVAL;
 }
 
@@ -120,13 +150,14 @@  static int vimc_streamer_stream_start(struct vimc_stream *stream,
  * Return: 0 if success, error code otherwise.
  */
 static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
-				       struct vimc_ent_device *ved)
+				       struct vimc_ent_device *cved)
 {
 	struct media_entity *entity;
 	struct media_device *mdev;
 	struct media_graph graph;
 	struct video_device *vdev;
 	struct v4l2_subdev *sd;
+	struct vimc_ent_device *ved = cved;
 	int ret;
 
 	entity = ved->ent;
@@ -170,6 +201,7 @@  static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
 		}
 	}
 
+	vimc_streamer_stream_terminate(cved);
 	vimc_streamer_pipeline_terminate(stream);
 	return -EINVAL;
 }
@@ -246,7 +278,7 @@  int vimc_streamer_s_stream(struct vimc_stream *stream,
 		if (stream->kthread)
 			return 0;
 
-		ret = vimc_streamer_stream_start(stream, ved);
+		ret = vimc_streamer_stream_start(ved);
 		if (ret)
 			return ret;
 
@@ -260,6 +292,7 @@  int vimc_streamer_s_stream(struct vimc_stream *stream,
 		if (IS_ERR(stream->kthread)) {
 			ret = PTR_ERR(stream->kthread);
 			dev_err(ved->dev, "kthread_run failed with %d\n", ret);
+			vimc_streamer_stream_terminate(ved);
 			vimc_streamer_pipeline_terminate(stream);
 			stream->kthread = NULL;
 			return ret;
@@ -269,18 +302,7 @@  int vimc_streamer_s_stream(struct vimc_stream *stream,
 		if (!stream->kthread)
 			return 0;
 
-		ret = kthread_stop(stream->kthread);
-		/*
-		 * kthread_stop returns -EINTR in cases when streamon was
-		 * immediately followed by streamoff, and the thread didn't had
-		 * a chance to run. Ignore errors to stop the stream in the
-		 * pipeline.
-		 */
-		if (ret)
-			dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
-
-		stream->kthread = NULL;
-
+		vimc_streamer_stream_terminate(ved);
 		vimc_streamer_pipeline_terminate(stream);
 	}