media: mc: entity: add alloc variant of pipeline_start
authorTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Wed, 31 Aug 2022 14:13:35 +0000 (16:13 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Sat, 24 Sep 2022 07:15:52 +0000 (09:15 +0200)
Add new variant of media_pipeline_start(), media_pipeline_alloc_start().

media_pipeline_alloc_start() can be used by drivers that do not need to
extend the media_pipeline. The function will either use the pipeline
already associated with the entity, if such exists, or allocate a new
pipeline.

When media_pipeline_stop() is called and the pipeline's use count drops
to zero, the pipeline is automatically freed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/mc/mc-entity.c
drivers/media/v4l2-core/v4l2-dev.c
include/media/media-entity.h
include/media/v4l2-dev.h

index 7fb97c6..ad153a4 100644 (file)
@@ -530,6 +530,8 @@ void __media_pipeline_stop(struct media_entity *entity)
 
        media_graph_walk_cleanup(graph);
 
+       if (pipe->allocated)
+               kfree(pipe);
 }
 EXPORT_SYMBOL_GPL(__media_pipeline_stop);
 
@@ -543,6 +545,42 @@ void media_pipeline_stop(struct media_entity *entity)
 }
 EXPORT_SYMBOL_GPL(media_pipeline_stop);
 
+__must_check int media_pipeline_alloc_start(struct media_entity *entity)
+{
+       struct media_device *mdev = entity->graph_obj.mdev;
+       struct media_pipeline *new_pipe = NULL;
+       struct media_pipeline *pipe;
+       int ret;
+
+       mutex_lock(&mdev->graph_mutex);
+
+       /*
+        * Is the entity already part of a pipeline? If not, we need to allocate
+        * a pipe.
+        */
+       pipe = media_entity_pipeline(entity);
+       if (!pipe) {
+               new_pipe = kzalloc(sizeof(*new_pipe), GFP_KERNEL);
+               if (!new_pipe) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               pipe = new_pipe;
+               pipe->allocated = true;
+       }
+
+       ret = __media_pipeline_start(entity, pipe);
+       if (ret)
+               kfree(new_pipe);
+
+out:
+       mutex_unlock(&mdev->graph_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
+
 /* -----------------------------------------------------------------------------
  * Links management
  */
index 7f933ff..945bb86 100644 (file)
@@ -1143,6 +1143,17 @@ void __video_device_pipeline_stop(struct video_device *vdev)
 }
 EXPORT_SYMBOL_GPL(__video_device_pipeline_stop);
 
+__must_check int video_device_pipeline_alloc_start(struct video_device *vdev)
+{
+       struct media_entity *entity = &vdev->entity;
+
+       if (entity->num_pads != 1)
+               return -ENODEV;
+
+       return media_pipeline_alloc_start(entity);
+}
+EXPORT_SYMBOL_GPL(video_device_pipeline_alloc_start);
+
 struct media_pipeline *video_device_pipeline(struct video_device *vdev)
 {
        struct media_entity *entity = &vdev->entity;
index aaf276f..a77933a 100644 (file)
@@ -100,10 +100,12 @@ struct media_graph {
 /**
  * struct media_pipeline - Media pipeline related information
  *
+ * @allocated:         Media pipeline allocated and freed by the framework
  * @start_count:       Media pipeline start - stop count
  * @graph:             Media graph walk during pipeline start / stop
  */
 struct media_pipeline {
+       bool allocated;
        int start_count;
        struct media_graph graph;
 };
@@ -1093,6 +1095,19 @@ void media_pipeline_stop(struct media_entity *entity);
 void __media_pipeline_stop(struct media_entity *entity);
 
 /**
+ * media_pipeline_alloc_start - Mark a pipeline as streaming
+ * @entity: Starting entity
+ *
+ * media_pipeline_alloc_start() is similar to media_pipeline_start() but instead
+ * of working on a given pipeline the function will use an existing pipeline if
+ * the entity is already part of a pipeline, or allocate a new pipeline.
+ *
+ * Calls to media_pipeline_alloc_start() must be matched with
+ * media_pipeline_stop().
+ */
+__must_check int media_pipeline_alloc_start(struct media_entity *entity);
+
+/**
  * media_devnode_create() - creates and initializes a device node interface
  *
  * @mdev:      pointer to struct &media_device
index 4946858..643da07 100644 (file)
@@ -608,6 +608,20 @@ void video_device_pipeline_stop(struct video_device *vdev);
 void __video_device_pipeline_stop(struct video_device *vdev);
 
 /**
+ * video_device_pipeline_alloc_start - Mark a pipeline as streaming
+ * @vdev: Starting video device
+ *
+ * video_device_pipeline_alloc_start() is similar to video_device_pipeline_start()
+ * but instead of working on a given pipeline the function will use an
+ * existing pipeline if the video device is already part of a pipeline, or
+ * allocate a new pipeline.
+ *
+ * Calls to video_device_pipeline_alloc_start() must be matched with
+ * video_device_pipeline_stop().
+ */
+__must_check int video_device_pipeline_alloc_start(struct video_device *vdev);
+
+/**
  * video_device_pipeline - Get the media pipeline a video device is part of
  * @vdev: The video device
  *