diff mbox series

[v1,2/5] media: mc: entity: Add entity iterator for media_pipeline

Message ID 20221212141621.724-3-laurent.pinchart@ideasonboard.com
State Accepted
Commit eac564de0915433716b83fad800d00675ccc6972
Headers show
Series media: Replace media graph walk in several drivers | expand

Commit Message

Laurent Pinchart Dec. 12, 2022, 2:16 p.m. UTC
Add a media_pipeline_for_each_entity() macro to iterate over entities in
a pipeline. This should be used by driver as a replacement of the
media_graph_walk API, as iterating over the media_pipeline uses the
cached list of pads and is thus more efficient.

Deprecate the media_graph_walk API to indicate it shouldn't be used in
new drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/mc/mc-entity.c | 37 +++++++++++++++++++
 include/media/media-entity.h | 69 ++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+)

Comments

Tomi Valkeinen Dec. 15, 2022, 12:48 p.m. UTC | #1
On 12/12/2022 16:16, Laurent Pinchart wrote:
> Add a media_pipeline_for_each_entity() macro to iterate over entities in
> a pipeline. This should be used by driver as a replacement of the
> media_graph_walk API, as iterating over the media_pipeline uses the
> cached list of pads and is thus more efficient.
> 
> Deprecate the media_graph_walk API to indicate it shouldn't be used in
> new drivers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/media/mc/mc-entity.c | 37 +++++++++++++++++++
>   include/media/media-entity.h | 69 ++++++++++++++++++++++++++++++++++++
>   2 files changed, 106 insertions(+)
> 
> diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
> index 70df2050951c..f19bb98071b2 100644
> --- a/drivers/media/mc/mc-entity.c
> +++ b/drivers/media/mc/mc-entity.c
> @@ -950,6 +950,43 @@ __media_pipeline_pad_iter_next(struct media_pipeline *pipe,
>   }
>   EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
>   
> +int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
> +				    struct media_pipeline_entity_iter *iter)
> +{
> +	return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
> +}
> +EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
> +
> +void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
> +{
> +	media_entity_enum_cleanup(&iter->ent_enum);
> +}
> +EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
> +
> +struct media_entity *
> +__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
> +				  struct media_pipeline_entity_iter *iter,
> +				  struct media_entity *entity)
> +{
> +	if (!entity)
> +		iter->cursor = pipe->pads.next;
> +
> +	while (iter->cursor != &pipe->pads) {
> +		struct media_pipeline_pad *ppad;
> +		struct media_entity *entity;
> +
> +		ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
> +		entity = ppad->pad->entity;
> +		iter->cursor = iter->cursor->next;
> +
> +		if (media_entity_enum_test_and_set(&iter->ent_enum, entity))
> +			return entity;

Shouldn't this be if (!media_entity...)? Doesn't 
media_entity_enum_test_and_set return true if the entity has already 
been seen, and thus we shouldn't return it?

> +	}
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
> +
>   /* -----------------------------------------------------------------------------
>    * Links management
>    */
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index e881e483b550..1b820cb6fed1 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -139,6 +139,17 @@ struct media_pipeline_pad_iter {
>   	struct list_head *cursor;
>   };
>   
> +/**
> + * struct media_pipeline_entity_iter - Iterator for media_pipeline_for_each_entity
> + *
> + * @ent_enum: The entity enumeration tracker
> + * @cursor: The current element
> + */
> +struct media_pipeline_entity_iter {
> +	struct media_entity_enum ent_enum;
> +	struct list_head *cursor;
> +};
> +

Same question here as for the previous one: can this be in the mc-entity.c?

  Tomi
Laurent Pinchart Dec. 15, 2022, 12:51 p.m. UTC | #2
Hi Tomi,

On Thu, Dec 15, 2022 at 02:48:43PM +0200, Tomi Valkeinen wrote:
> On 12/12/2022 16:16, Laurent Pinchart wrote:
> > Add a media_pipeline_for_each_entity() macro to iterate over entities in
> > a pipeline. This should be used by driver as a replacement of the
> > media_graph_walk API, as iterating over the media_pipeline uses the
> > cached list of pads and is thus more efficient.
> > 
> > Deprecate the media_graph_walk API to indicate it shouldn't be used in
> > new drivers.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >   drivers/media/mc/mc-entity.c | 37 +++++++++++++++++++
> >   include/media/media-entity.h | 69 ++++++++++++++++++++++++++++++++++++
> >   2 files changed, 106 insertions(+)
> > 
> > diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
> > index 70df2050951c..f19bb98071b2 100644
> > --- a/drivers/media/mc/mc-entity.c
> > +++ b/drivers/media/mc/mc-entity.c
> > @@ -950,6 +950,43 @@ __media_pipeline_pad_iter_next(struct media_pipeline *pipe,
> >   }
> >   EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
> >   
> > +int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
> > +				    struct media_pipeline_entity_iter *iter)
> > +{
> > +	return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
> > +}
> > +EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
> > +
> > +void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
> > +{
> > +	media_entity_enum_cleanup(&iter->ent_enum);
> > +}
> > +EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
> > +
> > +struct media_entity *
> > +__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
> > +				  struct media_pipeline_entity_iter *iter,
> > +				  struct media_entity *entity)
> > +{
> > +	if (!entity)
> > +		iter->cursor = pipe->pads.next;
> > +
> > +	while (iter->cursor != &pipe->pads) {
> > +		struct media_pipeline_pad *ppad;
> > +		struct media_entity *entity;
> > +
> > +		ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
> > +		entity = ppad->pad->entity;
> > +		iter->cursor = iter->cursor->next;
> > +
> > +		if (media_entity_enum_test_and_set(&iter->ent_enum, entity))
> > +			return entity;
> 
> Shouldn't this be if (!media_entity...)? Doesn't 
> media_entity_enum_test_and_set return true if the entity has already 
> been seen, and thus we shouldn't return it?

You're absolutely right. I'll fix that. I wonder how it escaped my
tests.

> > +	}
> > +
> > +	return NULL;
> > +}
> > +EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
> > +
> >   /* -----------------------------------------------------------------------------
> >    * Links management
> >    */
> > diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> > index e881e483b550..1b820cb6fed1 100644
> > --- a/include/media/media-entity.h
> > +++ b/include/media/media-entity.h
> > @@ -139,6 +139,17 @@ struct media_pipeline_pad_iter {
> >   	struct list_head *cursor;
> >   };
> >   
> > +/**
> > + * struct media_pipeline_entity_iter - Iterator for media_pipeline_for_each_entity
> > + *
> > + * @ent_enum: The entity enumeration tracker
> > + * @cursor: The current element
> > + */
> > +struct media_pipeline_entity_iter {
> > +	struct media_entity_enum ent_enum;
> > +	struct list_head *cursor;
> > +};
> > +
> 
> Same question here as for the previous one: can this be in the mc-entity.c?

I'm afraid not, for the same reason as in the previous patch.
diff mbox series

Patch

diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
index 70df2050951c..f19bb98071b2 100644
--- a/drivers/media/mc/mc-entity.c
+++ b/drivers/media/mc/mc-entity.c
@@ -950,6 +950,43 @@  __media_pipeline_pad_iter_next(struct media_pipeline *pipe,
 }
 EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
 
+int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
+				    struct media_pipeline_entity_iter *iter)
+{
+	return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
+}
+EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
+
+void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
+{
+	media_entity_enum_cleanup(&iter->ent_enum);
+}
+EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
+
+struct media_entity *
+__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
+				  struct media_pipeline_entity_iter *iter,
+				  struct media_entity *entity)
+{
+	if (!entity)
+		iter->cursor = pipe->pads.next;
+
+	while (iter->cursor != &pipe->pads) {
+		struct media_pipeline_pad *ppad;
+		struct media_entity *entity;
+
+		ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
+		entity = ppad->pad->entity;
+		iter->cursor = iter->cursor->next;
+
+		if (media_entity_enum_test_and_set(&iter->ent_enum, entity))
+			return entity;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
+
 /* -----------------------------------------------------------------------------
  * Links management
  */
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index e881e483b550..1b820cb6fed1 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -139,6 +139,17 @@  struct media_pipeline_pad_iter {
 	struct list_head *cursor;
 };
 
+/**
+ * struct media_pipeline_entity_iter - Iterator for media_pipeline_for_each_entity
+ *
+ * @ent_enum: The entity enumeration tracker
+ * @cursor: The current element
+ */
+struct media_pipeline_entity_iter {
+	struct media_entity_enum ent_enum;
+	struct list_head *cursor;
+};
+
 /**
  * struct media_link - A link object part of a media graph.
  *
@@ -1075,6 +1086,8 @@  int media_entity_get_fwnode_pad(struct media_entity *entity,
  * @graph: Media graph structure that will be used to walk the graph
  * @mdev: Pointer to the &media_device that contains the object
  *
+ * This function is deprecated, use media_pipeline_for_each_pad() instead.
+ *
  * The caller is required to hold the media_device graph_mutex during the graph
  * walk until the graph state is released.
  *
@@ -1087,6 +1100,8 @@  __must_check int media_graph_walk_init(
  * media_graph_walk_cleanup - Release resources used by graph walk.
  *
  * @graph: Media graph structure that will be used to walk the graph
+ *
+ * This function is deprecated, use media_pipeline_for_each_pad() instead.
  */
 void media_graph_walk_cleanup(struct media_graph *graph);
 
@@ -1097,6 +1112,8 @@  void media_graph_walk_cleanup(struct media_graph *graph);
  * @graph: Media graph structure that will be used to walk the graph
  * @entity: Starting entity
  *
+ * This function is deprecated, use media_pipeline_for_each_pad() instead.
+ *
  * Before using this function, media_graph_walk_init() must be
  * used to allocate resources used for walking the graph. This
  * function initializes the graph traversal structure to walk the
@@ -1112,6 +1129,8 @@  void media_graph_walk_start(struct media_graph *graph,
  * media_graph_walk_next - Get the next entity in the graph
  * @graph: Media graph structure
  *
+ * This function is deprecated, use media_pipeline_for_each_pad() instead.
+ *
  * Perform a depth-first traversal of the given media entities graph.
  *
  * The graph structure must have been previously initialized with a call to
@@ -1192,6 +1211,56 @@  __media_pipeline_pad_iter_next(struct media_pipeline *pipe,
 	     pad != NULL;						\
 	     pad = __media_pipeline_pad_iter_next((pipe), iter, pad))
 
+/**
+ * media_pipeline_entity_iter_init - Initialize a pipeline entity iterator
+ * @pipe: The pipeline
+ * @iter: The iterator
+ *
+ * This function must be called to initialize the iterator before using it in a
+ * media_pipeline_for_each_entity() loop. The iterator must be destroyed by a
+ * call to media_pipeline_entity_iter_cleanup after the loop (including in code
+ * paths that break from the loop).
+ *
+ * The same iterator can be used in multiple consecutive loops without being
+ * destroyed and reinitialized.
+ *
+ * Return: 0 on success or a negative error code otherwise.
+ */
+int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
+				    struct media_pipeline_entity_iter *iter);
+
+/**
+ * media_pipeline_entity_iter_cleanup - Destroy a pipeline entity iterator
+ * @iter: The iterator
+ *
+ * This function must be called to destroy iterators initialized with
+ * media_pipeline_entity_iter_init().
+ */
+void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter);
+
+struct media_entity *
+__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
+				  struct media_pipeline_entity_iter *iter,
+				  struct media_entity *entity);
+
+/**
+ * media_pipeline_for_each_entity - Iterate on all entities in a media pipeline
+ * @pipe: The pipeline
+ * @iter: The iterator (struct media_pipeline_entity_iter)
+ * @entity: The iterator entity
+ *
+ * Iterate on all entities in a media pipeline. This is only valid after the
+ * pipeline has been built with media_pipeline_start() and before it gets
+ * destroyed with media_pipeline_stop(). The iterator must be initialized with
+ * media_pipeline_entity_iter_init() before iteration, and destroyed with
+ * media_pipeline_entity_iter_cleanup() after (including in code paths that
+ * break from the loop).
+ */
+#define media_pipeline_for_each_entity(pipe, iter, entity)			\
+	for (entity = __media_pipeline_entity_iter_next((pipe), iter, NULL);	\
+	     entity != NULL;							\
+	     entity = __media_pipeline_entity_iter_next((pipe), iter, entity))
+
 /**
  * media_pipeline_alloc_start - Mark a pipeline as streaming
  * @pad: Starting pad