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 <kgu...@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
  *
  */
 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);
        }
 
-- 
2.17.1

Reply via email to