aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/media-entity.c
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2010-03-07 14:14:14 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 03:53:11 -0400
commita5ccc48a7c48610e7f92fa599406738d69195d51 (patch)
tree8b82352250fa0cef0bcbb7b4db760d98844d746d /drivers/media/media-entity.c
parent53e269c102fbaf77e7dc526b1606ad4a48e57200 (diff)
[media] media: Entity graph traversal
Add media entity graph traversal. The traversal follows enabled links by depth first. Traversing graph backwards is prevented by comparing the next possible entity in the graph with the previous one. Multiply connected graphs are thus not supported. Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@gmail.com> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/media-entity.c')
-rw-r--r--drivers/media/media-entity.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 5c31df9ed765..166f2b5505ce 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -84,6 +84,121 @@ media_entity_cleanup(struct media_entity *entity)
84} 84}
85EXPORT_SYMBOL_GPL(media_entity_cleanup); 85EXPORT_SYMBOL_GPL(media_entity_cleanup);
86 86
87/* -----------------------------------------------------------------------------
88 * Graph traversal
89 */
90
91static struct media_entity *
92media_entity_other(struct media_entity *entity, struct media_link *link)
93{
94 if (link->source->entity == entity)
95 return link->sink->entity;
96 else
97 return link->source->entity;
98}
99
100/* push an entity to traversal stack */
101static void stack_push(struct media_entity_graph *graph,
102 struct media_entity *entity)
103{
104 if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
105 WARN_ON(1);
106 return;
107 }
108 graph->top++;
109 graph->stack[graph->top].link = 0;
110 graph->stack[graph->top].entity = entity;
111}
112
113static struct media_entity *stack_pop(struct media_entity_graph *graph)
114{
115 struct media_entity *entity;
116
117 entity = graph->stack[graph->top].entity;
118 graph->top--;
119
120 return entity;
121}
122
123#define stack_peek(en) ((en)->stack[(en)->top - 1].entity)
124#define link_top(en) ((en)->stack[(en)->top].link)
125#define stack_top(en) ((en)->stack[(en)->top].entity)
126
127/**
128 * media_entity_graph_walk_start - Start walking the media graph at a given entity
129 * @graph: Media graph structure that will be used to walk the graph
130 * @entity: Starting entity
131 *
132 * This function initializes the graph traversal structure to walk the entities
133 * graph starting at the given entity. The traversal structure must not be
134 * modified by the caller during graph traversal. When done the structure can
135 * safely be freed.
136 */
137void media_entity_graph_walk_start(struct media_entity_graph *graph,
138 struct media_entity *entity)
139{
140 graph->top = 0;
141 graph->stack[graph->top].entity = NULL;
142 stack_push(graph, entity);
143}
144EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
145
146/**
147 * media_entity_graph_walk_next - Get the next entity in the graph
148 * @graph: Media graph structure
149 *
150 * Perform a depth-first traversal of the given media entities graph.
151 *
152 * The graph structure must have been previously initialized with a call to
153 * media_entity_graph_walk_start().
154 *
155 * Return the next entity in the graph or NULL if the whole graph have been
156 * traversed.
157 */
158struct media_entity *
159media_entity_graph_walk_next(struct media_entity_graph *graph)
160{
161 if (stack_top(graph) == NULL)
162 return NULL;
163
164 /*
165 * Depth first search. Push entity to stack and continue from
166 * top of the stack until no more entities on the level can be
167 * found.
168 */
169 while (link_top(graph) < stack_top(graph)->num_links) {
170 struct media_entity *entity = stack_top(graph);
171 struct media_link *link = &entity->links[link_top(graph)];
172 struct media_entity *next;
173
174 /* The link is not enabled so we do not follow. */
175 if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
176 link_top(graph)++;
177 continue;
178 }
179
180 /* Get the entity in the other end of the link . */
181 next = media_entity_other(entity, link);
182
183 /* Was it the entity we came here from? */
184 if (next == stack_peek(graph)) {
185 link_top(graph)++;
186 continue;
187 }
188
189 /* Push the new entity to stack and start over. */
190 link_top(graph)++;
191 stack_push(graph, next);
192 }
193
194 return stack_pop(graph);
195}
196EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
197
198/* -----------------------------------------------------------------------------
199 * Links management
200 */
201
87static struct media_link *media_entity_add_link(struct media_entity *entity) 202static struct media_link *media_entity_add_link(struct media_entity *entity)
88{ 203{
89 if (entity->num_links >= entity->max_links) { 204 if (entity->num_links >= entity->max_links) {