Hi Sakari, On Sat, Jan 15, 2022 at 10:02:21PM +0200, Laurent Pinchart wrote: > On Sat, Jan 15, 2022 at 07:39:33PM +0200, Sakari Ailus wrote: > > On Thu, Jan 13, 2022 at 05:00:42PM +0200, Laurent Pinchart wrote: > > > From: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > > > > > > The media_pipeline_start() function has two purposes: it constructs a > > > pipeline by recording the entities that are part of it, gathered from a > > > graph walk, and validate the media links. The pipeline pointer is stored > > > in the media_entity structure as part of this process, and the entity's > > > stream count is increased, to record that the entity is streaming. > > > > > > When multiple video nodes are present in a pipeline, > > > media_pipeline_start() is typically called on all of them, with the same > > > pipeline pointer. This is taken into account in media_pipeline_start() > > > by skipping validation for entities that are already part of the > > > pipeline, while returning an error if an entity is part of a different > > > pipeline. > > > > > > It turns out that this process is overly complicated. When > > > media_pipeline_start() is called for the first time, it constructs the > > > full pipeline, adding all entities and validating all the links. > > > Subsequent calls to media_pipeline_start() are then nearly no-ops, they > > > only increase the stream count on the pipeline and on all entities. > > > > > > The media_entity stream_count field is used for two purposes: checking > > > if the entity is streaming, and detecting when a call to > > > media_pipeline_stop() balances needs to reset the entity pipe pointer to > > > NULL. The former can easily be replaced by a check of the pipe pointer. > > > > > > Simplify media_pipeline_start() by avoiding the pipeline walk on all > > > calls but the first one, and drop the media_entity stream_count field. > > > media_pipeline_stop() is updated accordingly. > > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > > > --- > > > drivers/media/mc/mc-entity.c | 52 +++++++++++++++--------------------- > > > include/media/media-entity.h | 11 +++----- > > > 2 files changed, 26 insertions(+), 37 deletions(-) > > > > > > diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c > > > index f83e043f0f3b..8ab0913d8d82 100644 > > > --- a/drivers/media/mc/mc-entity.c > > > +++ b/drivers/media/mc/mc-entity.c > > > @@ -396,20 +396,21 @@ __must_check int __media_pipeline_start(struct media_entity *entity, > > > struct media_link *link; > > > int ret; > > > > > > - if (!pipe->streaming_count++) { > > > - ret = media_graph_walk_init(&pipe->graph, mdev); > > > - if (ret) > > > - goto error_graph_walk_start; > > > + if (pipe->streaming_count) { > > > + pipe->streaming_count++; > > > + return 0; > > > } > > > > > > + ret = media_graph_walk_init(&pipe->graph, mdev); > > > + if (ret) > > > + return ret; > > > + > > > media_graph_walk_start(&pipe->graph, entity); > > > > > > while ((entity = media_graph_walk_next(graph))) { > > > DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS); > > > DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS); > > > > > > - entity->stream_count++; > > > - > > > if (entity->pipe && entity->pipe != pipe) { > > > pr_err("Pipe active for %s. Can't start for %s\n", > > > entity->name, > > > @@ -418,12 +419,12 @@ __must_check int __media_pipeline_start(struct media_entity *entity, > > > goto error; > > > } > > > > > > - entity->pipe = pipe; > > > - > > > /* Already streaming --- no need to check. */ > > > - if (entity->stream_count > 1) > > > + if (entity->pipe) > > > continue; > > > > > > + entity->pipe = pipe; > > > + > > > if (!entity->ops || !entity->ops->link_validate) > > > continue; > > > > > > @@ -479,6 +480,8 @@ __must_check int __media_pipeline_start(struct media_entity *entity, > > > } > > > } > > > > > > + pipe->streaming_count++; > > > + > > > return 0; > > > > > > error: > > > @@ -489,24 +492,17 @@ __must_check int __media_pipeline_start(struct media_entity *entity, > > > media_graph_walk_start(graph, entity_err); > > > > > > while ((entity_err = media_graph_walk_next(graph))) { > > > - /* Sanity check for negative stream_count */ > > > - if (!WARN_ON_ONCE(entity_err->stream_count <= 0)) { > > > - entity_err->stream_count--; > > > - if (entity_err->stream_count == 0) > > > - entity_err->pipe = NULL; > > > - } > > > + entity_err->pipe = NULL; > > > > > > /* > > > - * We haven't increased stream_count further than this > > > - * so we quit here. > > > + * We haven't started entities further than this so we quit > > > + * here. > > > */ > > > if (entity_err == entity) > > > break; > > > } > > > > > > -error_graph_walk_start: > > > - if (!--pipe->streaming_count) > > > - media_graph_walk_cleanup(graph); > > > + media_graph_walk_cleanup(graph); > > > > > > return ret; > > > } > > > @@ -537,19 +533,15 @@ void __media_pipeline_stop(struct media_entity *entity) > > > if (WARN_ON(!pipe)) > > > return; > > > > > > + if (--pipe->streaming_count) > > > + return; > > > + > > > media_graph_walk_start(graph, entity); > > > > > > - while ((entity = media_graph_walk_next(graph))) { > > > - /* Sanity check for negative stream_count */ > > > - if (!WARN_ON_ONCE(entity->stream_count <= 0)) { > > > - entity->stream_count--; > > > - if (entity->stream_count == 0) > > > - entity->pipe = NULL; > > > - } > > > - } > > > + while ((entity = media_graph_walk_next(graph))) > > > + entity->pipe = NULL; > > > > > > - if (!--pipe->streaming_count) > > > - media_graph_walk_cleanup(graph); > > > + media_graph_walk_cleanup(graph); > > > > > > } > > > EXPORT_SYMBOL_GPL(__media_pipeline_stop); > > > diff --git a/include/media/media-entity.h b/include/media/media-entity.h > > > index 8546f13c42a9..e3c4fd1e3623 100644 > > > --- a/include/media/media-entity.h > > > +++ b/include/media/media-entity.h > > > @@ -268,7 +268,6 @@ enum media_entity_type { > > > * @pads: Pads array with the size defined by @num_pads. > > > * @links: List of data links. > > > * @ops: Entity operations. > > > - * @stream_count: Stream count for the entity. > > > * @use_count: Use count for the entity. > > > * @pipe: Pipeline this entity belongs to. > > > * @info: Union with devnode information. Kept just for backward > > > @@ -283,10 +282,9 @@ enum media_entity_type { > > > * > > > * .. note:: > > > * > > > - * @stream_count and @use_count reference counts must never be > > > - * negative, but are signed integers on purpose: a simple ``WARN_ON(<0)`` > > > - * check can be used to detect reference count bugs that would make them > > > - * negative. > > > + * The @use_count reference count must never be negative, but is a signed > > > + * integer on purpose: a simple ``WARN_ON(<0)`` check can be used to detect > > > + * reference count bugs that would make it negative. > > > */ > > > struct media_entity { > > > struct media_gobj graph_obj; /* must be first field in struct */ > > > @@ -305,7 +303,6 @@ struct media_entity { > > > > > > const struct media_entity_operations *ops; > > > > > > - int stream_count; > > > int use_count; > > > > > > struct media_pipeline *pipe; > > > @@ -867,7 +864,7 @@ struct media_pad *media_entity_remote_pad(const struct media_pad *pad); > > > */ > > > static inline bool media_entity_is_streaming(const struct media_entity *entity) > > > { > > > - return entity->stream_count > 0; > > > + return entity->pipe != NULL; > > > > I'd drop "!= NULL" part; it's redundant. > > I usually use "if (pointer)" or "if (!pointer)" without comparing to > NULL, but for some reason, when returning a bool, it feels more explicit > to me to use a comparison. I'm not sure why, maybe because, unlike with > if (), the implicit cast is only apparent when you read the signature of > the function ? Not that it's far away in this case, it's only two lines > up. > > > I'll do that when applying if that's fine. > > Fine with me, I don't mind either way. Thanks. Will you take this series for v5.18 ? > > > } > > > > > > /** -- Regards, Laurent Pinchart