Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxx> --- 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; +} + /* ----------------------------------------------------------------------------- * 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; + + /* + * Link validation on graph failed. We revert what we + * did and return the error. + */ + media_entity_graph_walk_start(&tmp_graph, tmp); + 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); }; 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); void media_entity_pipeline_stop(struct media_entity *entity); #define media_entity_call(entity, operation, args...) \ -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html