From: Laurent Pinchart <laurent.pinch...@ideasonboard.com>

Take internal routing information as reported by the entity has_route
operation into account during graph traversal to avoid following
unrelated links.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Signed-off-by: Michal Simek <michal.si...@xilinx.com>
Signed-off-by: Sakari Ailus <sakari.ai...@linux.intel.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo+rene...@jmondi.org>
---
 drivers/media/media-entity.c | 44 ++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 8e0ca8b1cfa2..3304e76bbafa 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -257,15 +257,6 @@ bool media_entity_has_route(struct media_entity *entity, 
unsigned int pad0,
 }
 EXPORT_SYMBOL_GPL(media_entity_has_route);
 
-static struct media_pad *
-media_pad_other(struct media_pad *pad, struct media_link *link)
-{
-       if (link->source == pad)
-               return link->sink;
-       else
-               return link->source;
-}
-
 /* push an entity to traversal stack */
 static void stack_push(struct media_graph *graph, struct media_pad *pad)
 {
@@ -336,7 +327,8 @@ static void media_graph_walk_iter(struct media_graph *graph)
 {
        struct media_pad *pad = stack_top(graph);
        struct media_link *link;
-       struct media_pad *next;
+       struct media_pad *remote;
+       struct media_pad *local;
 
        link = list_entry(link_top(graph), typeof(*link), list);
 
@@ -350,23 +342,41 @@ static void media_graph_walk_iter(struct media_graph 
*graph)
                return;
        }
 
-       /* Get the entity in the other end of the link . */
-       next = media_pad_other(pad, link);
+       /*
+        * Get the local pad, the remote pad and the entity at the other
+        * end of the link.
+        */
+       if (link->source->entity == pad->entity) {
+               remote = link->sink;
+               local = link->source;
+       } else {
+               remote = link->source;
+               local = link->sink;
+       }
+
+       /*
+        * Are the local pad and the pad we came from connected
+        * internally in the entity ?
+        */
+       if (!media_entity_has_route(pad->entity, pad->index, local->index)) {
+               link_top(graph) = link_top(graph)->next;
+               return;
+       }
 
        /* Has the entity already been visited? */
-       if (media_entity_enum_test_and_set(&graph->ent_enum, next->entity)) {
+       if (media_entity_enum_test_and_set(&graph->ent_enum, remote->entity)) {
                link_top(graph) = link_top(graph)->next;
                dev_dbg(pad->graph_obj.mdev->dev,
                        "walk: skipping entity '%s' (already seen)\n",
-                       next->entity->name);
+                       remote->entity->name);
                return;
        }
 
        /* Push the new entity to stack and start over. */
        link_top(graph) = link_top(graph)->next;
-       stack_push(graph, next);
-       dev_dbg(next->graph_obj.mdev->dev, "walk: pushing '%s':%u on stack\n",
-               next->entity->name, next->index);
+       stack_push(graph, remote);
+       dev_dbg(remote->graph_obj.mdev->dev, "walk: pushing '%s':%u on stack\n",
+               remote->entity->name, remote->index);
 }
 
 struct media_pad *media_graph_walk_next(struct media_graph *graph)
-- 
2.20.1

Reply via email to