Hi Sakari,

On Tuesday 17 January 2012 21:09:58 Sakari Ailus wrote:
> On Mon, Jan 16, 2012 at 03:35:07PM +0100, Laurent Pinchart wrote:
> > On Wednesday 11 January 2012 22:26:53 Sakari Ailus wrote:
> > > Signed-off-by: Sakari Ailus <sakari.ai...@iki.fi>
> > > ---
> > > 
> > >  drivers/media/media-entity.c |   73
> > > 
> > > ++++++++++++++++++++++++++++++++++++++++- include/media/media-entity.h
> > > |
> > > 
> > >  5 ++-
> > >  2 files changed, 74 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/drivers/media/media-entity.c
> > > b/drivers/media/media-entity.c index 056138f..62ef4b8 100644
> > > --- a/drivers/media/media-entity.c
> > > +++ b/drivers/media/media-entity.c
> > > @@ -196,6 +196,35 @@ media_entity_graph_walk_next(struct
> > > media_entity_graph *graph) }
> > > 
> > >  EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
> > > 
> > > +struct media_link_enum {
> > > + int i;
> > > + struct media_entity *entity;
> > > + unsigned long flags, mask;
> > > +};
> > > +
> > > +static struct media_link
> > > +*media_link_walk_next(struct media_link_enum *link_enum)
> > > +{
> > > + do {
> > > +         link_enum->i++;
> > > +         if (link_enum->i >= link_enum->entity->num_links)
> > > +                 return NULL;
> > > + } while ((link_enum->entity->links[link_enum->i].flags
> > > +           & link_enum->mask) != link_enum->flags);
> > > +
> > > + return &link_enum->entity->links[link_enum->i];
> > > +}
> > > +
> > > +static void media_link_walk_start(struct media_link_enum *link_enum,
> > > +                           struct media_entity *entity,
> > > +                           unsigned long flags, unsigned long mask)
> > > +{
> > > + link_enum->i = -1;
> > > + link_enum->entity = entity;
> > > + link_enum->flags = flags;
> > > + link_enum->mask = mask;
> > > +}
> > 
> > Do we really need a generic link walking code for a single user ? Merging
> > this in the function below would result in much simpler code.
> 
> It's a single funcition but it's being used from two locations in it.

Is it ? Not in this patch at least.

> I would keep it as-is, since performing the same in the function itself
> would much complicate it.

Are you sure about that ? :-)

> > > +
> > > 
> > >  /*
> > > 
> > > -----------------------------------------------------------------------
> > > --- --- * Pipeline management
> > > 
> > >   */
> > > 
> > > @@ -214,23 +243,63 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
> > > 
> > >   * pipeline pointer must be identical for all nested calls to
> > >   * media_entity_pipeline_start().
> > >   */
> > > 
> > > -void media_entity_pipeline_start(struct media_entity *entity,
> > > -                          struct media_pipeline *pipe)
> > > +__must_check int media_entity_pipeline_start(struct media_entity
> > > *entity, +                                             struct 
> > > media_pipeline *pipe)
> > > 
> > >  {
> > >  
> > >   struct media_device *mdev = entity->parent;
> > >   struct media_entity_graph graph;
> > > 
> > > + struct media_entity *tmp = entity;
> > > + int ret = 0;
> > > 
> > >   mutex_lock(&mdev->graph_mutex);
> > >   
> > >   media_entity_graph_walk_start(&graph, entity);
> > >   
> > >   while ((entity = media_entity_graph_walk_next(&graph))) {
> > > 
> > > +         struct media_entity_graph tmp_graph;
> > > +         struct media_link_enum link_enum;
> > > +         struct media_link *link;
> > > +
> > > 
> > >           entity->stream_count++;
> > >           WARN_ON(entity->pipe && entity->pipe != pipe);
> > >           entity->pipe = pipe;
> > > 
> > > +
> > > +         if (!entity->ops || !entity->ops->link_validate)
> > > +                 continue;
> > > +
> > > +         media_link_walk_start(&link_enum, entity,
> > > +                               MEDIA_LNK_FL_ENABLED,
> > > +                               MEDIA_LNK_FL_ENABLED);
> > > +
> > > +         while ((link = media_link_walk_next(&link_enum))) {
> > > +                 if (link->sink->entity != entity)
> > > +                         continue;
> > > +
> > > +                 ret = entity->ops->link_validate(link);
> > > +                 if (ret < 0 && ret != -ENOIOCTLCMD)
> > > +                         break;
> > > +         }
> > > +         if (!ret || ret == -ENOIOCTLCMD)
> > > +                 continue;
> > 
> > What about a goto error instead ? That would keep the error code out of
> > the loop.
> 
> Fixed.
> 
> > > +
> > > +         /*
> > > +          * Link validation on graph failed. We revert what we
> > > +          * did and return the error.
> > > +          */
> > > +         media_entity_graph_walk_start(&tmp_graph, tmp);
> > 
> > I've never liked tmp as a variable name. As the graph variable isn't used
> > anymore from this point on, you can reuse it. tmp can then be renamed to
> > something more descriptive.
> 
> I re-use graph, and tmp is called entity_err now.
> 
> > > +         do {
> > > +                 tmp = media_entity_graph_walk_next(&tmp_graph);
> > > +                 tmp->stream_count--;
> > > +                 if (entity->stream_count == 0)
> > > +                         entity->pipe = NULL;
> > > +         } while (tmp != entity);
> > > +
> > > +         break;
> > > 
> > >   }
> > >   
> > >   mutex_unlock(&mdev->graph_mutex);
> > > 
> > > +
> > > + return ret == 0 || ret == -ENOIOCTLCMD ? 0 : ret;
> > > 
> > >  }
> > >  EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
> > > 
> > > diff --git a/include/media/media-entity.h
> > > b/include/media/media-entity.h index cd8bca6..f7ba80a 100644
> > > --- a/include/media/media-entity.h
> > > +++ b/include/media/media-entity.h
> > > @@ -46,6 +46,7 @@ struct media_entity_operations {
> > > 
> > >   int (*link_setup)(struct media_entity *entity,
> > >   
> > >                     const struct media_pad *local,
> > >                     const struct media_pad *remote, u32 flags);
> > > 
> > > + int (*link_validate)(struct media_link *link);
> > 
> > What about documenting the operation in Documentation/media-framework.txt
> > ?
> 
> Yup.
> 
> ---
> Link validation
> ---------------
> 
> Link validation is performed from media_entity_pipeline_start() for any
> entity which has sink pads in the pipeline. The
> media_entity::link_validate() callback is used for that purpose. In
> link_validate() callback, the entity driver should check that the
> properties of the source pad of the connected entity and its own sink pad
> match. ---
>
> > >  };
> > >  
> > >  struct media_entity {
> > > 
> > > @@ -140,8 +141,8 @@ void media_entity_graph_walk_start(struct
> > > media_entity_graph *graph, struct media_entity *entity);
> > > 
> > >  struct media_entity *
> > >  media_entity_graph_walk_next(struct media_entity_graph *graph);
> > > 
> > > -void media_entity_pipeline_start(struct media_entity *entity,
> > > -         struct media_pipeline *pipe);
> > > +__must_check int media_entity_pipeline_start(struct media_entity
> > > *entity, +                                             struct 
> > > media_pipeline *pipe);
> > 
> > As well as keeping the media_entity_pipeline_start() documentation
> > up-to-date in the same file :-)
> 
> Added a note it may return an error.

-- 
Regards,

Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to